Docker Commitの落とし穴: ボリュームマウントされたデータがイメージに保存されない理由と対策
Dockerを使っていると、コンテナの状態を新しいイメージとして保存したい場面が多々あります。その際に便利なコマンドがdocker commit
です。しかし、docker commit
を使っても期待通りにデータが保存されないことがあります。この記事では、私が経験した問題とその原因、そして解決策について詳しく説明します。
docker commit コマンドの基本
まず、docker commit
コマンドは、起動中のコンテナのファイルシステムの状態を新しいイメージとして保存するためのものです。基本的な使い方は以下の通りです。
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
# or
docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
詳細な使い方は公式ドキュメントを参照してください。
問題の発生
私のユースケースでは、開発環境のDBコンテナの状態を新しいイメージに保存する必要がありました。具体的には、DBコンテナ内でSQLを実行してデータベースに変更を加えた後、その状態をdocker commit
で保存しようとしました。
しかし、docker commit
で作成した新しいイメージからコンテナを起動すると、SQLで追加・変更したデータが存在しないという問題が発生しました。
原因の究明
この問題の原因は非常にシンプルでした。docker commit
コマンドは、ボリュームマウントされたデータをイメージに含めないという仕様があったのです。
公式ドキュメントの記述
公式ドキュメントには以下のように記載されています。
The commit operation will not include any data contained in volumes mounted inside the container.
つまり、コンテナ内でボリュームマウントされたデータは、docker commit
操作によって新しいイメージに含まれないのです。
ボリュームマウントの仕組み
Dockerのイメージは、Dockerのファイルシステムの情報のみを持ちます。バインドマウント(bind mount)やボリューム(volume)は、その違いが曖昧になることがありますが、共通しているのは「外部的なストレージ・ボリューム」であるという点です。
バインドマウントの具体例
以下のようなdocker-compose.yml
ファイルでバインドマウントを利用している場合を考えます。
services:
db:
volumes:
- /path/to/mount/on_host:/mount/target/on_container
この設定では、コンテナ内の/mount/target/on_container
ディレクトリには、ホストの/path/to/mount/on_host
ディレクトリがマウントされます。この状態でdocker commit
を実行しても、マウントされた外部のストレージはイメージに含まれません。
解決策
この問題を解決するためには、いくつかの方法があります。
データをコンテナ内にコピー
ボリュームマウントされたデータを一時的にコンテナ内の別のディレクトリにコピーし、その状態でdocker commit
を実行する方法です。
docker cp /mount/target/on_container /path/to/copy
docker commit CONTAINER_ID new_image_name
Dockerfileを利用
もう一つの方法は、Dockerfileを使ってイメージを作成する方法です。Dockerfileを使うことで、データのコピーや設定を自動化できます。
マウントする方法ではなく、Dockerfile で COPY してはじめからイメージに必要なファイルを保存しておけば、コンテナ起動時にそのファイルを参照出来ます。
私のケースだとこの方法を使って、DBのファイルをイメージにコピーして、DBコンテナが起動する時点で、データが入っている状態を再現することが出来ました。
FROM base_image
COPY /path/to/mount/on_host /mount/target/on_container
まとめ
docker commitコマンドは便利ですが、ボリュームマウントされたデータがイメージに含まれないという仕様に注意が必要でした。docker commit ってあんまり使っているひといないですが、参考になれば幸いです。私は今後は docker commit 使いません(多分)
Discussion