Dockerコンテナは非常に便利ですが、デフォルトでは「揮発性」を持っています。つまり、コンテナを削除すると、その中で作成・変更されたデータも一緒に消えてしまうのです。これでは、Difyのチャット履歴や設定、データベースの内容などを保存しておくことができません。
この問題を解決するのが「Dockerボリューム (Volume)」です。ボリュームは、コンテナのライフサイクルとは独立してデータを永続化するための仕組みです。
この記事は、『【Docker】Dockerとは?Dify導入のための基本概念と使い方ガイド』および『【Docker】Dockerfile入門ガイド:イメージ作成の基本からベストプラクティスまで』の補足記事として、Dockerボリュームとは何か、種類と使い分け、そして docker-compose.yml での設定方法までを詳しく解説します。
1. Dockerボリュームとは? なぜ必要なのか?
Dockerボリュームとは、コンテナとは別に存在するデータの保管場所です。コンテナ内の特定のディレクトリ(フォルダ)を、この外部の保管場所に接続(マウント)することで、データの永続化を実現します。
PCに例えると…
- コンテナ: 電源を切ると内容が消える「PCのメモリ (RAM)」のような一時的な作業スペース。
- ボリューム: PCの電源を切ってもデータが残る「外付けHDD/SSD」のような永続的な保管場所。
コンテナ内の /app/data ディレクトリをボリュームに接続しておけば、コンテナを削除・再作成しても、新しいコンテナが同じボリュームに接続することで、以前のデータをそのまま引き継ぐことができます。これは、データベースのデータ、ユーザーがアップロードしたファイル、設定ファイルなどを扱う上で必須の機能です。
ボリュームの主な利点
- データの永続化: コンテナを削除してもデータが消えません。
- データの共有: 複数のコンテナで同じボリュームを共有できます。
- バックアップ/リストア: ボリュームのデータをバックアップ・リストアしやすくなります。
- パフォーマンス: Dockerが管理するボリュームは、ホストOSのファイルシステムに最適化されている場合があります。
- 安全性: Dockerがボリュームのライフサイクルを管理するため、ホストOSの重要なファイルを誤って変更するリスクが低減されます(バインドマウントを除く)。
2. Dockerボリュームの主な種類と使い分け
Dockerでデータを永続化する方法(マウントタイプ)は主に3つあり、それぞれ特徴と適した用途が異なります。
① 名前付きボリューム (Named Volumes) – (推奨)
- 管理場所: Dockerが管理する領域(通常はホストOSの
/var/lib/docker/volumes/配下など)。 - 特徴:
- ユーザーが任意の名前(例:
postgres_data,dify_uploads)を付けて管理します。 - Dockerコマンド (
docker volume ls,docker volume rmなど) で管理できます。 - ホストOSのディレクトリ構造に依存せず、可搬性が高いです。
- Docker公式が最も推奨している方法です。
- ユーザーが任意の名前(例:
- 主な用途:
- データベースのデータファイル (例: PostgreSQL, MySQL)
- アプリケーションが生成するデータ (例: Difyのナレッジファイル、ユーザーアップロードファイル)
- 複数コンテナ間で共有したいデータ
docker-compose.ymlでの指定:services: db: image: postgres:15 volumes: # "db_data" という名前付きボリュームをコンテナ内の /var/lib/postgresql/data にマウント - db_data:/var/lib/postgresql/data volumes: # トップレベルで "db_data" ボリュームを定義 (Dockerが自動作成・管理) db_data:
② バインドマウント (Bind Mounts)
- 管理場所: ホストOS上の任意のディレクトリやファイル。
- 特徴:
- ホストOSの特定のパスをコンテナ内のパスに直接マッピングします。
- ホストOSとコンテナ間でファイルがリアルタイムに同期されます。
- Dockerからは管理されません (
docker volume lsには表示されません)。 - ホストOSのファイルシステムに直接アクセスするため、権限設定やセキュリティに注意が必要です。コンテナ内のプロセスがホストのファイルを変更できてしまいます。
- 主な用途:
- 開発環境でのソースコードの同期: ローカルPCでコードを編集すると、即座にコンテナ内のアプリケーションに反映されるため、開発効率が向上します。
- ホストOS上の設定ファイルをコンテナに読み込ませる場合。
- コンテナが生成したログファイルをホストOSに直接書き出す場合。
docker-compose.ymlでの指定:services: web: build: . volumes: # ホストのカレントディレクトリ(.)をコンテナ内の /app にマウント - .:/app # ホストの /path/to/config.conf をコンテナ内の /etc/myapp.conf にマウント - /path/to/config.conf:/etc/myapp.conf:ro # :ro は読み取り専用
③ 匿名ボリューム (Anonymous Volumes)
- 管理場所: Dockerが管理する領域(名前付きボリュームと同じ)。
- 特徴:
- ユーザーが名前を指定せず、Dockerがランダムなハッシュ値のような名前を自動的に付けます。
docker volume lsで確認できますが、どのコンテナが使っていたか管理しにくいです。- コンテナ削除時に自動で削除されないため、意図せず残り続けてディスク容量を圧迫することがあります (
docker volume pruneで一括削除可能)。
- 主な用途:
- 名前を付けて管理する必要はないが、一時的にデータを永続化したい場合。(しかし、通常は名前付きボリュームを使う方が管理しやすいです)。
docker-compose.ymlでの指定:services: temp_data_service: image: alpine volumes: # コンテナ内の /data ディレクトリに対して匿名ボリュームをマウント - /data(トップレベルの
volumes:での定義は不要)
使い分けのまとめ
| 種類 | 管理者 | 特徴 | 主な用途 | Difyでの例 |
|---|---|---|---|---|
| 名前付きボリューム | Docker | 推奨, Docker管理, 可搬性高い | DBデータ, アプリ生成データ, 共有データ | postgres_data, dify_storage など |
| バインドマウント | ホストOS | リアルタイム同期, ホスト依存, セキュリティ注意 | 開発時のソースコード同期, 設定ファイル読込 | Difyソースコード開発時, Nginx設定 |
| 匿名ボリューム | Docker | 名前なし, 管理しにくい, 意図せず残る可能性 | 一時的な永続化 (非推奨) | (通常使わない) |
3. Dockerボリュームの作成とマウント方法【基本操作】
ボリュームを作る
# my_volumeという名前のボリュームを作成
docker volume create my_volume
作ったボリュームを確認する
# ボリューム一覧を表示
docker volume ls
ボリュームを使う(マウント)
# ボリュームをコンテナにマウントして起動
docker run -d \
--name my_container \
-v my_volume:/app/data \
nginx
解説:
-v my_volume:/app/data:my_volumeをコンテナ内の/app/dataという場所に接続する- これで、
/app/dataに保存したファイルはmy_volumeに保存される
データが本当に残るか確認してみよう
# コンテナを削除
docker rm -f my_container
# 新しいコンテナで同じボリュームを使用
docker run -it --rm -v my_volume:/app/data ubuntu bash
# コンテナ内で ls /app/data を実行すると、前のデータが残っている!
このように、ボリュームはコンテナとは別に管理されます。
4. 不要なボリュームの削除とクリーンアップ方法
特定のボリュームを削除
# 使用中でないボリュームを削除
docker volume rm my_volume
使っていないボリュームをまとめて削除
# 未使用ボリュームを一括削除
docker volume prune
安全な削除手順
- 使用中のコンテナを確認:
docker ps - ボリューム一覧を確認:
docker volume ls - 本当に不要か確認:
docker volume inspect ボリューム名 - 削除実行:
docker volume rm ボリューム名
5. 実践的な使用例
Webサイトのデータを保存
# HTMLファイルを保存するボリューム付きでNginxを起動
docker run -d \
--name my_website \
-p 8080:80 \
-v website_files:/usr/share/nginx/html \
nginx
# ボリュームにHTMLファイルをコピー
docker cp index.html my_website:/usr/share/nginx/html/
データベースのデータを保存
# データベースのデータを保存するボリューム付きでMySQLを起動
docker run -d \
--name my_database \
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
6.よくある質問と対処法
ボリュームの中身を確認したい
# ボリュームの詳細情報を表示
docker volume inspect my_volume
# ボリュームの中身を確認
docker run --rm -v my_volume:/data ubuntu ls -la /data
ボリュームをバックアップしたい
# ボリュームをtar形式でバックアップ
docker run --rm -v my_volume:/data -v $(pwd):/backup ubuntu \
tar czf /backup/backup.tar.gz -C /data .
ボリュームを復元したい
# バックアップからボリュームを復元
docker run --rm -v my_volume:/data -v $(pwd):/backup ubuntu \
tar xzf /backup/backup.tar.gz -C /data
7. ボリュームの同期(コピー)の挙動
docker compose up で初めてボリュームをマウントする際、データがどのようにコピーされるかは、ボリュームの種類と状態によって異なります。
- バインドマウント:
- 常にホストOS側が正となります。コンテナイメージ内に同名のパスにファイルが存在していても、ホストOSのディレクトリの内容で上書きされます。
- 名前付きボリューム:
- 空のボリュームをマウントした場合: コンテナ側が正。コンテナイメージ内のマウント対象パスにファイルがあれば、それがボリュームにコピーされます。(例: 初回起動時のDB初期データ)
- データが入ったボリュームをマウントした場合: ボリューム側が正。コンテナイメージ内のファイルは無視され、ボリュームの既存データがそのままコンテナから見えます。
- 匿名ボリューム:
- 常にコンテナ側が正。コンテナイメージ内のマウント対象パスにファイルがあれば、それがボリュームにコピーされます。
この挙動の違いを理解しておくことは、特にデータベースの初期設定などで重要になります。
8. docker-compose.yml でのボリューム設定
docker-compose.yml では、主に2箇所でボリュームに関する設定を行います。
① services: 内の volumes:
各サービス(コンテナ)に対して、どのボリューム(またはホストパス)をコンテナ内のどのパスにマウントするかを指定します。
services:
myservice:
image: myimage
volumes:
# 名前付きボリュームのマウント (推奨)
- my_named_volume:/path/in/container
# バインドマウント (ホストのカレントディレクトリをマウント)
- .:/app
# バインドマウント (ホストの特定ファイルを読み取り専用でマウント)
- ./config.json:/etc/config.json:ro
# 匿名ボリュームのマウント (非推奨)
- /var/log/app
- 書式:
<ホスト側パス or ボリューム名>:<コンテナ側パス>[:<オプション>] - オプション:
ro(読み取り専用),rw(読み書き可能: デフォルト)
② トップレベルの volumes:
ファイル全体の一番下に記述し、名前付きボリュームを定義します。Docker Compose は、ここで定義されたボリュームが存在しない場合、自動的に作成します。
# ... services: の定義 ...
volumes:
# "my_named_volume" という名前付きボリュームを定義
my_named_volume:
# オプション: 既存のボリュームを使いたい場合
# external: true
# name: specific_volume_name # Dockerホスト上の特定の名前を指定
# "db_data" という名前付きボリュームを定義 (オプションなし)
db_data:
external: true: Docker Compose の外で作成された(例:docker volume createコマンドで作成した)既存のボリュームを利用する場合に指定します。
9. Dockerボリュームの管理コマンド
基本的なボリューム管理コマンドです。
docker volume ls存在するボリューム(名前付き・匿名)の一覧を表示します。docker volume create <ボリューム名>名前付きボリュームを手動で作成します。docker volume inspect <ボリューム名>ボリュームの詳細情報(マウントポイントのパスなど)を表示します。docker volume rm <ボリューム名>指定したボリュームを削除します。(コンテナが使用中の場合は削除できません)docker volume pruneどのコンテナからも使用されていないボリューム(主に匿名ボリュームや、コンテナ削除後に残った名前付きボリューム)を一括で削除します。削除前にdocker volume lsで確認することを強く推奨します。
まとめ
Dockerボリュームは、コンテナ内のデータを永続化し、安全に管理するための必須機能です。
- 基本的には名前付きボリュームを使い、Dockerに管理を任せるのが推奨されます。
- 開発時のコード同期にはバインドマウントが便利ですが、ホストOSへの影響に注意が必要です。
docker-compose.ymlを使えば、ボリュームの定義とマウントを簡単に管理できます。- データの同期(コピー)の挙動は、ボリュームの種類と状態で異なることを理解しておきましょう。
Difyを運用する上で、データベース (db コンテナ) やストレージ (storage ディレクトリなど) がどのボリュームにマウントされているかを把握しておくことは、バックアップやトラブルシューティングの際に非常に重要になります。


コメント