DockerfileのVOLUME命令の理解
Docker ボリュームは、コンテナの外部に永続的なデータを保存するために使用されます。それらは、アプリケーションによって使用される設定ファイル、データベース、およびキャッシュが個々のコンテナインスタンスを超えて存続できるようにします。
コンテナを docker run コマンドの -v フラグを使用して起動する際、ボリュームをマウントできます。これには、名前付きボリュームを参照するか、ホストディレクトリをコンテナのファイルシステムにバインドマウントする方法があります。
DockerfileのVOLUME命令を使用することで、イメージビルド時にボリュームを定義することも可能です。このメカニズムは、イメージから起動されたコンテナが永続的なストレージを利用できることを保証します。この記事では、この命令の使用方法と、それが有効なユースケースについて学ぶことができます。
Dockerfileでのボリュームの定義
DockerfileのVOLUME命令は、指定されたコンテナパスにボリュームマウントポイントを作成します。コンテナが起動するたびに、Dockerホストのファイルシステムからボリュームがマウントされます。
次の例のDockerfileは、以下の位置にボリュームを定義しています。
/opt/app/dataコンテナパス。新しいコンテナは、自動的にディレクトリにボリュームをマウントします。
FROM ubuntu:22.04
VOLUME /opt/app/data
ボリュームマウントをテストできるように、イメージを構築してください:
docker build -t volumes-test:latest .参照として既存のボリュームのリストを取得します:
docker volume ls
DRIVER VOLUME NAME
local demo-volume
テストイメージを使ってコンテナを開始してください:
docker run -it volume-test:latest
root@07be7bde68c2:/#
docker volume ls コマンドを再実行して、新しいボリュームが作成されたことを確認してください。
docker volume ls
DRIVER VOLUME NAME
local 3198bf857fdcbb8758c5ec7049f2e31a40b79e329f756a68725d83e46976b7a8
local demo-volume
テストコンテナのシェルから出て、コンテナを停止させます。
root@07be7bde68c2:/# exit
exit
ボリュームとそのデータは引き続き存在し続けます:
docker volume ls
DRIVER VOLUME NAME
local 3198bf857fdcbb8758c5ec7049f2e31a40b79e329f756a68725d83e46976b7a8
local demo-volume
一つの命令で、スペースで区切られた文字列またはJSON配列として複数のボリュームを定義できます。以下の両方の形式は、コンテナが起動する際に2つのユニークなボリュームを作成しマウントします:
VOLUME /opt/app/data /opt/app/config
OR
VOLUME ["/opt/app/data", "/opt/app/config"]
初期ボリュームコンテンツの入力
ボリュームは、前のイメージビルドステップによってマウントディレクトリに配置されたコンテンツで自動的に補充されます:
FROM ubuntu:22.04
COPY default-config.yaml /opt/app/config/default-config.yaml
VOLUME /opt/app/config
このDockerfileは、既存のdefault-config.yamlファイルで初期化されるボリュームを定義します。コンテナは、ファイルが存在するかどうかを確認することなく/opt/app/config/default-config.yamlを読み取ることができます。
VOLUME命令の後にボリュームの内容に加えられた変更は破棄されます。この例では、コンテナが起動した後もdefault-config.yamlファイルは利用可能です。なぜなら、/opt/app/configがボリュームとしてマークされた後にrmコマンドが実行されるからです。
FROM ubuntu:22.04
COPY default-config.yaml /opt/app/config/default-config.yaml
VOLUME /opt/app/config
RUN rm /opt/app/config/default-config.yaml
コンテナ起動時のVOLUME指示の上書き
VOLUME命令によって作成されたボリュームは、長い一意のハッシュで自動的に命名されます。その名前を変更することはできないため、どのボリュームがコンテナによって積極的に使用されているのかを特定するのが難しい場合があります。
これらのボリュームが現れるのを防ぐために、通常どおり docker run -v を用いてコンテナにボリュームを手動で定義できます。以下のコマンドは、名前付きボリュームをコンテナの /opt/app/config ディレクトリに明示的にマウントし、Dockerfile の VOLUME 命令を冗長にします。
docker run -it -v config:/opt/app/config volumes-test:latestボリューム命令はいつ使用すべきですか?
VOLUME 指示は、データベースサーバーやファイルストレージをパッケージするイメージなどで永続性の使用を強制したい場合に便利です。VOLUME 指示を使用することで、適用するための -v フラグを覚えておく必要がなく、コンテナを簡単に開始することができます。
VOLUMEは、永続データを保存するコンテナパスのドキュメントとしても機能します。この指示をDockerfileに含めることで、誰でもアプリケーションに不慣れであっても、コンテナがデータをどこに保管しているかを特定できるようになります。
ボリュームの落とし穴
VOLUME には欠点がないわけではありません。その最大の問題は、イメージビルドとの相互作用です。VOLUME 命令を基にしたイメージをビルドのベースイメージとして使用する場合、ボリュームマウントポイント内のコンテンツを変更すると予期しない動作をします。
以前の注意点は今も当てはまります: VOLUME 命令の後のコマンドの効果は無視されます。VOLUME はベースイメージに存在するため、自分の Dockerfile のすべてはその命令の後に来るものであり、ディレクトリのデフォルトの内容を変更することはできません。裏では、一時コンテナをビルドのために起動すると、ビルドの終了時に破棄されるホスト上の新しいボリュームが作成されます。変更は出力イメージに戻されることはありません。
自動ボリュームマウントは他の状況でも問題を引き起こすことがあります。時々、ユーザーは評価やデバッグの目的で、ボリュームなしで一時的なコンテナを起動することを好むかもしれません。VOLUMEを指定すると、自動マウントを無効にすることができないため、この可能性は失われます。この指示を使用するコンテナが定期的に起動されると、ホスト上に多くの冗長なボリュームが蓄積される原因となります。
要約
DockerfileのVOLUME命令を使用すると、イメージビルド時にボリュームマウントを定義できます。これにより、イメージから起動したコンテナには、ユーザーがdocker runコマンドの-vフラグを省略しても、永続的なデータストレージが利用可能であることが保証されます。
この動作は、持続性が重要であったり、多くのボリュームが必要な画像にとって有用です。しかし、VOLUME 命令はユーザーの期待を壊し、独自の動作を導入するため、注意をもって記述する必要があります。必要なボリュームを自動的に作成する Docker Compose ファイルを提供する方が、しばしばより良い解決策となります。
