Dockerでファイルを直接マウントすると書き換え時に面倒くさい
ついついやってしまいがちですが、以下のように ディレクトリではなくファイルをDockerコンテナにマウントするとちょっと面倒くさいことになります。
version: "3"
services:
caddy_server:
image: caddy
volumes:
# Caddyfile というファイルをそのままマウントしている
- ./Caddyfile:/etc/caddy/Caddyfile
これがどういうことになるかというと、Dockerコンテナの外からマウントしたファイルを書き換えても何故か反映されないといったことが起きます。
私が遭遇したケースだと下記2ケースでそれが発生しました。
- Vimでマウントしているファイルを書き換える
- Ansibleでマウントしているファイルを置き換える
両者に共通しているのは、ファイルを書き換える際にinodeを変更してしまうというところです。
inodeを変更するというのはつまり、一部のツールはファイルを上書きする際、上書きというよりはパスが同じだけの別ファイルに置き換える動作をしてしまいます。
Dockerコンテナに直接マウントしているファイルを書き換えるケースでは、コンテナ外からマウントしているファイルを書き換えると、一見ファイルを変更したように見えても、Dockerがマウントしているファイルは元のまま書き換わらないことがあります。 別ファイルに置き換えられたファイルをDockerコンテナが参照することはありません。
じゃあどうするか?
置き換えツールにinodeを変更させないまま上書きさせることもできないわけではないのでしょうが(例:vimのbackupcopyオプション)、一般的な解決策とは言えないので、こういった設定ファイルをDockerコンテナにマウントする際は下記のいずれかの方法を取ることになります。
- 設定ファイルを置き換えるたびにDockerコンテナを作成しなおす
- Dockerコンテナにファイルではなくディレクトリをマウントする
コンテナのダウンタイムが問題にならない場合、マウントしている設定ファイルを変更した場合は、きっぱりコンテナをゼロから作り直したほうが色々気にしなくて済みます。
コンテナのダウンタイムが問題になる場合、設定ファイルを含んだディレクトリをマウントする方が無難です。
version: "3"
services:
caddy_server:
image: caddy
volumes:
# Caddyfile というファイルを含んだディレクトリ(./config_dir)をマウントする
- ./config_dir:/etc/caddy
本件、割とAnsibleでコンテナの設定ファイル書き換えているとありがちだと思います。ファイルをマウントする時は気をつけましょう。