「ホスト側のソースコードを修正したのに、なぜかDockerコンテナ側に変更が反映されない…」
この問題にぶち当たり、備忘録として仕組みと原因、対処法を残しておきます。
結論
今回のようにホスト側の修正がコンテナに反映されない場合、よくある原因は、ソースコードが volume mount されておらず、COPY によってビルド時点の内容がイメージ内に取り込まれていることです。
そのため、ホスト上のファイルを更新しても、起動中のコンテナ内のコードは自動では変わりません。
なぜ反映されないのか?(仕組みの解説)
1. COPY はビルド時点のコードを固定する
Dockerfile に以下のような記述がある場合:
COPY application /opt/webclient/application
これは docker build を実行したタイミングで、ホストのファイルをコンテナイメージの中に切り離して固定(焼き込み)するという意味になります。
一度ビルドした後は、mount していない限り、コンテナ内のコードはビルド時点の内容を使い続けます。
そのため、ホスト側だけを編集しても、コンテナ内のファイルには反映されません。
2. docker-compose.yml でマウントされているか?
例えば、docker-compose.yml で以下のようにログ領域しか Volume 指定されていない場合:
services:
scheduler:
build:
context: .
dockerfile: Dockerfile-scheduler
volumes:
- /var/log/application:/var/log/application # ログファイルのみ共有されている
-
/var/log/application(ログ): ホストと同期されているため変更や出力がリアルタイムに反映される -
/opt/webclient/application(ソースコード): マウントされていないため、ビルド時の古いコードがそのまま動く
状況の確認方法(本当にコードが古いか調べる)
ホスト側のファイルを見るのではなく、実行中のコンテナ内部に入って確認する必要があります。
# 1. 実行中のコンテナに入る
docker exec -it <コンテナ名またはコンテナID> bash
# 2. コンテナ内の該当ディレクトリに移動してファイルを確認
cd /opt/webclient/application
cat <確認したいファイル名>
対処法(変更を反映させる手順)
パターンA:イメージを再ビルドする
ソースコードがイメージ内に焼き込まれている構成の場合は、イメージを作り直してコンテナを再起動します。
# docker-compose を使っている場合
docker compose build scheduler
docker compose up -d scheduler
# 単体 Docker コマンドの場合
docker build -f Dockerfile-scheduler -t my-scheduler .
docker run -d my-scheduler
パターンB:開発環境用にソースコードをマウントする
開発環境でコード変更をすぐ反映したい場合は、Compose でソースコードを volume mount する方法が便利です。
ただし、この構成は主に開発向けであり、本番環境ではイメージを再ビルドして反映する運用の方が管理しやすいケースが一般的です。
services:
scheduler:
# ...
volumes:
- ./application:/opt/webclient/application # ホストのapplicationディレクトリを同期
- /var/log/application:/var/log/application
まとめ
- ホストのファイルを書き換えても反映されない時は、
COPYで焼き込まれていてマウントされていない可能性を疑う。 - 本当に反映されているか確認するときは、
docker execでコンテナの中に入って中身を見る。 - 修正を反映するには イメージの再ビルド(
docker compose build) が必要!