h-ysk
May 26, 2025, 11:52pm
1
Torizon OS上で動作するQtアプリケーション(GUIアプリケーション)を開発しております。
GUIアプリケーションは実行ファイルと同階層に配置されたdataフォルダ内に、
GUIの設定値を保存したJsonファイルを保持しており、GUIから設定値を操作し書き込みを行っております。
Dockerコンテナの再起動によって、書き込んだはずの設定がクリアされてしまうため、
コンテナ外のフォルダとマウントする必要があると考え、ボリューム機能の利用を検討しております。
ボリューム機能は、docker-compose.ymlへの設定が必要と考え
以下の記載のサイトを参考に設定を行いましたが、データが保持されませんでした。
https://matsuand.github.io/docs.docker.jp.onthefly/storage/volumes/#use-a-volume-with-docker-compose
version: "3.9"
services:
Guiqtdemo-debug:
build:
context: .
dockerfile: Dockerfile.debug
image: ${LOCAL_REGISTRY}:5002/Guiqtdemo-debug:${TAG}
ports:
# SSH debug
- 2231:2231
# gdbserver
- 2232:2232
# qml debug
- 2233:2233
devices:
- "/dev/ttyRPMSG31:/dev/ttyRPMSG31"
- "/dev/snd"
volumes:
- type: bind
source: /tmp
target: /tmp
- type: bind
source: /dev
target: /dev
read_only: false
- type: bind
bind:
propagation: shared
source: /media
target: /media
- data-volume:/home/torizon/GUIApp/data
device_cgroup_rules:
# ... for tty0
- "c 4:0 rmw"
# ... for tty7
- "c 4:7 rmw"
# ... for /dev/input devices
- "c 13:* rmw"
- "c 199:* rmw"
# ... for /dev/dri devices
- "c 226:* rmw"
depends_on: [
weston
]
Guiqtdemo:
build:
context: .
dockerfile: Dockerfile
image: ${DOCKER_LOGIN}/Guiqtdemo:${TAG}
devices:
- "/dev/ttyRPMSG31:/dev/ttyRPMSG31"
- "/dev/snd"
volumes:
- type: bind
source: /tmp
target: /tmp
- type: bind
source: /dev
target: /dev
- type: bind
bind:
propagation: shared
source: /media
target: /media
- data-volume:/home/torizon/GUIApp/data
device_cgroup_rules:
# ... for tty0
- "c 4:0 rmw"
# ... for tty7
- "c 4:7 rmw"
# ... for /dev/input devices
- "c 13:* rmw"
- "c 199:* rmw"
# ... for /dev/dri devices
- "c 226:* rmw"
depends_on: [
weston
]
weston:
# image: torizon/weston${GPU}:3
image: ${LOCAL_REGISTRY}:5002/torizon/weston${GPU}:3
environment:
- ACCEPT_FSL_EULA=1
# Required to get udev events from host udevd via netlink
network_mode: host
volumes:
- type: bind
source: /tmp
target: /tmp
- type: bind
source: /dev
target: /dev
- type: bind
source: /run/udev
target: /run/udev
- type: bind
source: /etc/xdg/weston/
target: /etc/xdg/weston/]
- data-volume:/home/torizon/GUIApp/data
cap_add:
- CAP_SYS_TTY_CONFIG
# Add device access rights through cgroup...
device_cgroup_rules:
# ... for tty0
- "c 4:0 rmw"
# ... for tty1
- "c 4:1 rmw"
# ... for tty7
- "c 4:7 rmw"
# ... for /dev/input devices
- "c 13:* rmw"
- "c 199:* rmw"
# ... for /dev/dri devices
- "c 226:* rmw"
backup:
image: backup-service
volumes:
- data-volume:/home/torizon/GUIApp/data
volumes:
data-volume:
お手数をおかけして申し訳ありませんが、
GUIアプリから変更を加えたファイルをコンテナ再起動後も保持するための具体的な設定方法をご教示いただけますでしょうか。
1 Like
Hi, I’m the Toradex AI Assistant.
I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox . For follow-up questions to me, please use @ToradexAI in your post.
Did you like my answer?
こんにちは、ご質問ありがとうございます。
コンテナ再起動後も設定ファイル(Json)を保持するには、Dockerのボリュームを正しく設定する必要があります。Torizonでは公式ガイドのとおり、ボリュームの宣言 とサービスごとのマウント指定 が重要です。
1. docker-compose.yml
によるボリュームの宣言
volumes:
data-volume:
driver: local
このように明示的にdriver: local
を指定します。
2. サービスごとのボリュームマウント指定
サービス内のvolumes指定は下記のように記載します:
services:
Guiqtdemo-debug:
# ...(省略)
volumes:
# その他のバインドマウント省略
- type: volume
source: data-volume
target: /home/torizon/GUIApp/data
Guiqtdemo:
# ...(省略)
volumes:
- type: volume
source: data-volume
target: /home/torizon/GUIApp/data
ポイント
type: volume
でボリュームとしてマウントすることを明記します。
source
はcomposeファイル下部のvolumes
で宣言したdata-volume
です。
target
はアプリケーション内でデータフォルダとして実際に使用しているパス と一致させてください。
他サービス(例:westonやbackup)でこのボリュームをマウントする必要がなければ、不要です。
3. ディレクトリ権限を確認
初回起動時、/home/torizon/GUIApp/data
ディレクトリがアプリ内で作成される場合は、コンテナユーザー(例:torizonユーザー)がこのディレクトリのオーナーになる ことを確認してください。
4. 例:修正されたdocker-compose.yml抜粋
version: "3.9"
services:
Guiqtdemo-debug:
# ...(省略)
volumes:
- type: bind
source: /tmp
target: /tmp
- type: bind
source: /dev
target: /dev
read_only: false
- type: bind
bind:
propagation: shared
source: /media
target: /media
- type: volume
source: data-volume
target: /home/torizon/GUIApp/data
# ...(省略)
Guiqtdemo:
# ...(省略)
volumes:
- type: bind
source: /tmp
target: /tmp
- type: bind
source: /dev
target: /dev
- type: bind
bind:
propagation: shared
source: /media
target: /media
- type: volume
source: data-volume
target: /home/torizon/GUIApp/data
volumes:
data-volume:
driver: local
5. 既存ボリュームに初期データをコピーしたい場合
初回起動時、/home/torizon/GUIApp/data
内に何もファイルがなければ、data-volume
は空になります。
初期データ登録が必要な場合は、公式ドキュメントの例 のように、entrypoint
スクリプト等で初期コピー処理を追加することを検討してください。
参考ドキュメント:
何かご不明な点がありましたら、どうぞご質問ください。
Best regards, Toradex AI Assistant.
h-ysk
May 28, 2025, 9:43am
4
ご提示いただいた内容で /home/torizon/GUIApp/dataをボリュームとして設定したところ配置されたJsonファイルに書き込み権限が無く編集できませんでした。
GUIアプリケーション起動時に、
”/home/torizon/GUIApp/data”に配置されたJsonファイルに対して
file.open(QIODevice::ReadWrite);を行うのですが
Permission deniedとなり、書き込み権限がFalseとなっておりました。
GUIアプリケーションから新規にテキストやJsonファイルを
”/home/torizon/GUIApp/data”上に作成しようとすると、同様に権限が無く実行不可でした。
しかし、ボリュームで設定した以外のパス
例えば”/home/torizon/GUIApp”や”/home/torizon/GUIApp/data3”などには
GUIアプリケーションから新規ファイル作成を行うことができました(書き込み権限がtrueであることも確認済み)。
ボリュームで指定したフォルダのみ書き込み不可のような動きに見えるのですが
その他、確認すべき内容、必要な設定などございますでしょうか。
GUIアプリケーションからは”/home/torizon/GUIApp/data”上のJsonファイルを読み書きし
そのフォルダ内のJsonファイルの設定がコンテナ再起動後も維持されることを想定しております。
@h-ysk 様
ご返信が遅くなり申し訳ございません。
フォローアップの内容を確認いたしました。
TorizonCore OS では、ルートファイルシステムがデフォルトで読み取り専用 (read-only)となっており、そのためアプリケーションからデータの永続化を行う場合には、
書き込みが許可された特定のフォルダ を使用することが推奨されています。
その中でも一般的にカスタマイズ情報や設定ファイルの永続化には /etc
フォルダ がよく利用されております。
このフォルダは TorizonCore において 永続化用の overlayfs に含まれており、書き込みが可能 です。
今回のように GUI アプリケーションから JSON 設定ファイルを保存/更新したい場合 は、
以下のような形で /etc
配下に専用のサブフォルダを作成し、そこにファイルを配置する方法をおすすめいたします:
例)
/etc/GUIApp/settings.json
公式ドキュメントでも /etc
を使ったカスタマイズ方法が紹介されております ので、
あわせてご参照いただけますと幸いです:
Torizon OS Customization
( /etc
配下への設定ファイル配置方法の参考になります)
恐れ入りますがご確認いただければと思います。
アルバロ。
h-ysk
June 10, 2025, 3:10am
6
ご回答いただきありがとうございます。
以下のように理解しましたが間違いありませんでしょうか
・docker-compose.ymlでの設定において
”/home/torizon/GUIApp/data”指定の箇所を”/etc/GUIApp/”に変更し永続化パスをetcに設定
・GUIアプリにおいて、書き込み先パスも”/etc/GUIApp/settings.json”に変更
また、/etcを使用するうえで、その他、Dockerファイル、docker-compose.ymlなど設定が必要な項目はありますでしょうか。
併せて確認させていただきたいのですが
一般的に/etcに関しては権限周りの設定を行わないとフォルダの作成やファイルへの書き込み不可となると思われます。
以下の想定処理に必要な権限周りの設定方法を伺いたいです。
(例えばDockerファイル、docker-compose.ymlの設定など)
-想定処理-
・今回、初回起動で”/etc/GUIApp/settings.json”のフォルダが存在しない場合
フォルダを作成するか、または、あらかじめ用意しておいたフォルダを(Jsonファイルごと)コピーする、いずれかの処理を想定しております。
・GUIアプリからの”/etc/GUIApp/settings.json”に対する読み込み\書き込みを想定
・”/etc/GUIApp/settings.json”の永続化を想定
@h-ysk
ご理解いただいております内容はその通りで問題ございません。
加えて /etc
フォルダ利用時の具体的な設定例と、初回起動時のフォルダ作成+ファイル配置方法について、以下のような形をおすすめいたします。
※ 下記のサンプルコードは AI により自動生成された参考例となっております。
実際のご使用環境やアプリケーション仕様により、適宜調整が必要になる場合がございます。
基本的な実装のベースとしてご参考いただき、プロジェクトに合わせてご活用いただけますと幸いです。
entrypoint.sh にて:
/etc/GUIApp
が無ければ作成
settings.json が無ければデフォルトを /etc/GUIApp/settings.json
にコピー
その後 GUI アプリを起動
#!/bin/sh
# /etc/GUIApp が無ければ作成
if [ ! -d /etc/GUIApp ]; then
echo "Creating /etc/GUIApp..."
sudo mkdir -p /etc/GUIApp
sudo chown torizon:torizon /etc/GUIApp
fi
# settings.json が無ければデフォルトをコピー
if [ ! -f /etc/GUIApp/settings.json ]; then
echo "Copying default settings.json..."
cp /tmp/default-settings.json /etc/GUIApp/settings.json
fi
# GUI アプリを実行
exec /usr/local/bin/your_app_binary
Dockerfile / docker-compose.yml にて:
/etc/GUIApp
をボリュームとしてマウント → 永続化
entrypoint.sh を ENTRYPOINT として設定
version: "3.9"
services:
guiqtdemo:
build: .
volumes:
# /etc/GUIApp を永続化
- /etc/GUIApp:/etc/GUIApp
environment:
- QT_QPA_PLATFORM=wayland
# 他に必要な設定があれば追加
FROM torizon/qt5-wayland (例: 使用しているベースイメージに合わせて変更)
# 必要なパッケージがあればインストール
# RUN apt-get update && apt-get install -y <packages>
# アプリをコピー
COPY GUIApp/your_app_binary /usr/local/bin/your_app_binary
# デフォルト設定ファイルをコピー (コンテナ内の一時場所へ)
COPY default-settings/settings.json /tmp/default-settings.json
# エントリポイントスクリプトをコピー
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
# ユーザー切り替え (例: torizonユーザーを使う場合)
USER torizon
# エントリポイントを設定
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
上記のような形にしていただくことで:
/etc/GUIApp
配下は TorizonCore OS 側で永続化対象 となるため、コンテナ再起動後も保持されます。
アプリ側では /etc/GUIApp/settings.json
を読み書き可能になります。
初回起動時は entrypoint.sh 内で自動的に初期設定を配置できます。
注意点 :
/etc
配下のパーミッションに注意 → 初回作成時に chown torizon:torizon
などで権限設定しておくと良いです。
docker-compose.yml
にて /etc/GUIApp
を明示的にボリューム指定していただくことで、アプリの更新時にも設定は保持 されます。