あけましておめでとうございます
今年も宜しくお願い致します。
tl;dr
WordPress の公式 Docker イメージを利用して Dockerfile を書いていたら、コンテナ内の /var/www/html
以下でファイルの操作が出来なかったので、なぜだろうと思って調べたのでメモしておきます。
Dockerfile
あれーっ
以下のような Dockerfile を書いていました。
FROM wordpress:5.6.0 ADD test.txt /var/www/html/test.txt RUN echo "xxxxxxxxxxxxxxxxxxxxxxxxx" >> /var/www/html/test.txt
ビルドしてコンテナを起動すると、以下のような結果となることを期待していました。
$ docker build -t docker-sandbox . && echo "-------" && docker run --rm docker-sandbox:latest cat /var/www/html/test.txt (ビルドの様子) ------- xxxxxxxxxxxxxxxxxxxxxxxxx
実際に実行してみると、以下のように出力されました。
$ docker build -t docker-sandbox . && echo "-------" && docker run --rm docker-sandbox:latest cat /var/www/html/test.txt Sending build context to Docker daemon 2.56kB Step 1/3 : FROM wordpress:5.6.0 ---> bc5f6567b763 Step 2/3 : ADD test.txt /var/www/html/test.txt ---> Using cache ---> 271e40aceba6 Step 3/3 : RUN echo "xxxxxxxxxxxxxxxxxxxxxxxxx" >> /var/www/html/test.txt ---> Using cache ---> 5d26f3ec24c6 Successfully built 5d26f3ec24c6 Successfully tagged docker-sandbox:latest -------
あれーっと思って、docker history
でコマンドのビルド履歴を見てみると、以下のように xxxxxxxxxxxxxxxxxxxxxxxxx
の書き込みで SIZE が 0B
となっていることに気づきました。
$ docker history docker-sandbox:latest | less IMAGE CREATED CREATED BY SIZE COMMENT 5d26f3ec24c6 6 minutes ago /bin/sh -c echo "xxxxxxxxxxxxxxxxxxxxxxxxx" … 0B 271e40aceba6 6 minutes ago /bin/sh -c #(nop) ADD file:bd8c9270f5699bc59… 0B bc5f6567b763 2 weeks ago /bin/sh -c #(nop) CMD ["apache2-foreground"] 0B <missing> 2 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B (略)
おお。
なんだろう、/var/www/html
ディレクトリに何か特殊なことをしているのだろうか... ということで、WordPress コンテナイメージの Dockerfile を見てみました。
WordPress コンテナイメージの Dockerfile を見てみる
以下のように、/var/www/html
パスが VOLUME
指定されていました。
(略) chmod -R 777 wp-content VOLUME /var/www/html COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD ["%%CMD%%"]
ほうほう、VOLUME
指定していると、そのパスは何か特殊なことが起きるようです。
VOLUME を指定すると
ドキュメント
Dockerfile のリファレンスを見てみましょう。
Changing the volume from within the Dockerfile
以下のように記述されていました。
If any build steps change the data within the volume after it has been declared, those changes will be discarded.
日本語訳すると、以下の通りです。
ビルドステップでボリューム内のデータが宣言された後に変更された場合、その変更は破棄されます。
なるほど、なるほど。
今回だと、すでに WordPress コンテナをビルドする際に VOLUME /var/www/html
が指定されている為、Dockerfile 内で /var/www/html
以下のファイルを操作 (ファイルに文字列を上書き) しようとしても操作が出来なったというオチですね。
完全に理解した... というわけではありません... なぜ、Dockerfile 内で VOLUME
を指定した以降、その指定されたパスでの変更が破棄されるのか、その理由を知りたくて、ドキュメントを漁ったり、Docker のソースコード (buildkit や moby) をななめ読みしてみたりしましたが、理由は解らず、自分の Docker 力の無さに凹みました。
とりあえず、今は、これは仕様ということで理解しておきます。