docker compose up で Dockerfile の変更が反映されない
docker compose up は既定ではビルド済みイメージをそのまま使い、Dockerfile やソースを変更しても再ビルドしない。
--build を付けて起動するのが基本。
それでも反映されない場合はレイヤーキャッシュとボリュームの覆い被せを疑う。
公開: 更新:
要約
Dockerfile やソースコードを変更したのに docker compose up で反映されないのは、up が既定では再ビルドしないためです。
up はビルド済みイメージが存在すればそれをそのまま使ってコンテナを起動します。
変更を反映するには --build フラグを付けるのが基本です(docker compose up リファレンス(新しいタブで開く))。
それでも反映されない場合は、レイヤーキャッシュとボリュームによる覆い被せを順に確認します。
実行例
message.txt を v2 に書き換えてから docker compose up -d をやり直しても、イメージのビルドは走らず既存のコンテナが起動し直されただけで、ログは message: v1 のままだった。--build を付けて起動するとイメージが作り直されてコンテナが再作成され、message: v2 が出力されている。
$ docker compose up -d
Image compose-rebuild-demo-web Building
#1 [internal] load local bake definitions
#1 reading from stdin 593B 0.0s done
#1 DONE 0.0s
#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 109B done
#2 DONE 0.0s
#3 [internal] load metadata for docker.io/library/alpine:3
#3 DONE 0.0s
#4 [internal] load .dockerignore
#4 transferring context: 2B done
#4 DONE 0.0s
#5 [1/2] FROM docker.io/library/alpine:3@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b
#5 resolve docker.io/library/alpine:3@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b 0.0s done
#5 DONE 0.0s
#6 [internal] load build context
#6 transferring context: 50B done
#6 DONE 0.0s
#7 [2/2] COPY message.txt /message.txt
#7 CACHED
#8 exporting to image
#8 exporting layers done
#8 exporting manifest sha256:66b19322543c5bb8f95c2216120450b949fc292968e8413c0f8b61e65744e125 done
#8 exporting config sha256:7ea035c1eb721e281d89e975c2d0afe70f4e510a1ae0ffdd87c1653a01a6194a done
#8 exporting attestation manifest sha256:def497c9b663fba09bc64c67241d71d0fe9fda53ffd6c8c1386c5a8d2d9d58c5 0.0s done
#8 exporting manifest list sha256:9a2625de0f5d38e99e4d9febc17d1e796e186ffccb9027bc2d75711bbbfc2d38 done
#8 naming to docker.io/library/compose-rebuild-demo-web:latest done
#8 unpacking to docker.io/library/compose-rebuild-demo-web:latest 0.0s done
#8 DONE 0.1s
#9 resolving provenance for metadata file
#9 DONE 0.0s
Image compose-rebuild-demo-web Built
Network compose-rebuild-demo_default Creating
Network compose-rebuild-demo_default Created
Container compose-rebuild-demo-web-1 Creating
Container compose-rebuild-demo-web-1 Created
Container compose-rebuild-demo-web-1 Starting
Container compose-rebuild-demo-web-1 Started$ docker compose logs --tail 1 web
web-1 | message: v1$ cat message.txt
message: v2$ docker compose up -d
Container compose-rebuild-demo-web-1 Starting
Container compose-rebuild-demo-web-1 Started$ docker compose logs --tail 1 web
web-1 | message: v1$ docker compose up --build -d
Image compose-rebuild-demo-web Building
#1 [internal] load local bake definitions
#1 reading from stdin 593B 0.0s done
#1 DONE 0.0s
#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 109B done
#2 DONE 0.0s
#3 [internal] load metadata for docker.io/library/alpine:3
#3 DONE 0.0s
#4 [internal] load .dockerignore
#4 transferring context: 2B done
#4 DONE 0.0s
#5 [internal] load build context
#5 transferring context: 50B done
#5 DONE 0.0s
#6 [1/2] FROM docker.io/library/alpine:3@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b
#6 resolve docker.io/library/alpine:3@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b 0.0s done
#6 DONE 0.0s
#7 [2/2] COPY message.txt /message.txt
#7 CACHED
#8 exporting to image
#8 exporting layers done
#8 exporting manifest sha256:39f59196c1cfe72ff268499ab5c0af333c37d6844f2d1f34ef21bdc04414fbba done
#8 exporting config sha256:24d4cbbd5b922fd965a470a93053d02ef47a1f6846aa45772910d25efd0a57eb done
#8 exporting attestation manifest sha256:bb21d64785e1fa2c08daf7c4bf79a1e642b1703cc4561e139ee5ed844c00c333 0.0s done
#8 exporting manifest list sha256:bad2b7ace69453a35e2627c30acd4bca7c46939516955c44c14892a5cbab01a6 done
#8 naming to docker.io/library/compose-rebuild-demo-web:latest done
#8 unpacking to docker.io/library/compose-rebuild-demo-web:latest 0.0s done
#8 DONE 0.1s
#9 resolving provenance for metadata file
#9 DONE 0.0s
Image compose-rebuild-demo-web Built
Container compose-rebuild-demo-web-1 Recreate
Container compose-rebuild-demo-web-1 Recreated
Container compose-rebuild-demo-web-1 Starting
Container compose-rebuild-demo-web-1 Started$ docker compose logs --tail 1 web
web-1 | message: v2— 2026-09-14 時点の出力
検証環境
- 検証日
- 実行環境
local host (Windows 11 Home, Docker 29.1.3)- バージョン
- Node.js 22.14.0
- npm 10.9.2
- Git 2.48.1.windows.1
- Docker 29.1.3
この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。
よくある原因
- up は再ビルドしない:
build:を定義していても、イメージが既にあれば up はビルドを省略する。
Dockerfile を編集しただけでは次の up に反映されない。 - レイヤーキャッシュ:
--buildを付けても、COPY対象に変化が無いと判断されたレイヤー以降のみ再実行される。apt-get installのような外部状態に依存する手順は古いキャッシュが残りやすい。 - ボリュームの覆い被せ:
volumes: - .:/appのような bind mount があると、イメージ内の/appはホスト側の内容で上書きされる。
イメージをいくら作り直してもコンテナ内に見えるのはホストのファイル。 - 古いローカルイメージ:
image: myapp:latestのような指定では、レジストリを更新してもローカルのlatestタグが残っていればそちらが使われる。
解決策
1. --build を付けて起動する
docker compose up --build -d開発中はこの形をデフォルトにしておくと「反映されない」事故を避けられます。
2. キャッシュを無効化して作り直す
docker compose build --no-cache web
docker compose up -d webベースイメージの更新やパッケージインストールの結果を確実に取り込みたいときは --no-cache でビルドし直します。
3. ボリューム定義を確認する
docker compose config展開後の設定で volumes: を確認し、イメージの変更を反映したいパスが bind mount や named volume で覆われていないか確かめます。
覆われている場合、反映すべきはイメージではなくマウント元です。
4. リモートイメージを取得し直す
docker compose pull
docker compose up -dimage: 指定のサービスは pull で最新を取得してから起動します。