Docker Compose を使っていると、
「さっき build したのに、また build が始まった」
「Dockerfile を変えたのに反映されない」
「volume を変えたら build し直す必要があるのか分からない」
ということがあります。
自分も最初は、変更したらとりあえず docker compose build すればよいと思っていました。
ただ、実際には build / up / recreate / volume の役割が違います。
この記事は、Docker Compose の rebuild 挙動で混乱した時の切り分けメモです。
結論
ざっくり言うと、こうです。
| 変更内容 | 必要な操作 |
|---|---|
| Dockerfile を変えた | build |
| image に含めるファイルを変えた | build |
build.args を変えた |
build |
ports を変えた |
up / recreate |
volumes を変えた |
up / recreate |
environment を変えた |
up / recreate |
| bind mount しているソースを変えた | build 不要 |
| volume で上書きされている場所 | build しても反映されないことがある |
基本はこれです。
# Dockerfileを変えた
docker compose up -d --build
# composeの起動設定だけ変えた
docker compose up -d
# 反映が怪しいのでコンテナを作り直す
docker compose up -d --force-recreate
重要なのは、build は image を作る処理で、up は container を起動する処理ということです。
起きたこと
Docker Compose を使っていて、以下のようなことがありました。
-
docker compose buildした直後なのに、また build が走る -
docker compose upで build される時とされない時がある - Dockerfile を変えたのに、コンテナ内で変化が見えない
-
volumesを変えた時に build すべきなのか分からない -
COPY . .以降が毎回実行されているように見える
このあたりが混ざると、かなり分かりづらいです。
build と up の違い
まず、docker compose build は image を作るコマンドです。
docker compose build
一方、docker compose up は container を起動するコマンドです。
docker compose up -d
ただし、compose に build: が書かれていて、必要な image がまだない場合は、up のタイミングで build が走ることがあります。
services:
app:
build:
context: .
そのため、初回は以下だけでも build されることがあります。
docker compose up -d
Dockerfile を変更した後なら、明示的に build します。
docker compose up -d --build
Dockerfileを変えたら build が必要
Dockerfile を変えた場合は、基本的に build が必要です。
docker compose up -d --build
または、
docker compose build
docker compose up -d
です。
例えば以下を変えた場合です。
FROMRUN apt-get install ...COPYCMDARG- image に含める設定ファイル
-
package.jsonやcomposer.jsonなど、build 中に使うファイル
このあたりは image の中身に関わるので、build 対象です。
ports / volumes / environment の変更は build ではない
一方、docker-compose.yml の変更でも、build が不要なものがあります。
services:
app:
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
environment:
APP_ENV: local
このような ports / volumes / environment の変更は、基本的に container の起動設定です。
まずは普通に起動し直します。
docker compose up -d
反映が怪しければ、コンテナを作り直します。
docker compose up -d --force-recreate
ここで build しても、問題の場所が image ではなく container 設定なら、あまり意味がありません。
volumeで上書きされている場所はbuildしても変わらない
個人的に一番混乱しやすいのはここです。
Dockerfile でファイルをコピーしていても、
COPY ./src /var/www/html
compose 側で同じ場所を volume mount していると、
services:
app:
volumes:
- ./src:/var/www/html
コンテナ起動時に /var/www/html はホスト側の ./src で上書きされます。
つまり、image の中には COPY でファイルが入っていても、起動後のコンテナでは volume の内容が見えます。
この状態で何度 build しても、/var/www/html には volume 側のファイルが見えます。
なので、
DockerfileでCOPYしたのに反映されない
と思った時は、まず volume で同じパスを上書きしていないか見ます。
COPY . . があるとキャッシュが効きにくいことがある
Dockerfile に以下のような行があるとします。
COPY . .
これは build context 全体を image にコピーします。
そのため、対象ファイルが何か変わると、この行以降のキャッシュが効かなくなることがあります。
例:
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
この場合、package.json が変わらなければ npm install まではキャッシュされやすいです。
ただし、COPY . . の対象に入っているファイルが変わると、それ以降の RUN npm run build は再実行されやすくなります。
不要なファイルが build context に入っていると、build が重くなります。
.dockerignore を確認する
COPY . . を使うなら、.dockerignore を確認します。
例えば Node.js 系なら、最低限このあたりは除外します。
node_modules
.git
dist
build
.cache
*.log
不要なファイルまで build context に入っていると、キャッシュも効きづらくなります。
build の様子を見たい場合は、詳細ログを出します。
docker compose build --progress=plain
キャッシュを完全に無視するなら、
docker compose build --no-cache
です。
ただし、普段から --no-cache を使う必要はありません。
「キャッシュのせいで古いものを見ているかも」と疑う時の切り分け用です。
よく使う判断
Dockerfileを変えた
docker compose up -d --build
composeのportsやvolumesを変えた
docker compose up -d
反映が怪しければ、
docker compose up -d --force-recreate
buildしたのにファイルが変わらない
volume で上書きしていないか確認します。
volumes:
- ./src:/var/www/html
毎回buildが重い
.dockerignore を確認します。
docker compose build --progress=plain
まとめ
Docker Compose の build / rebuild が分かりづらい時は、まず以下を分けると整理しやすいです。
build = image を作る
up = container を起動する
recreate = container を作り直す
volume = container 起動時に外側のファイルを見せる
Dockerfile を変えたなら build。
docker compose up -d --build
compose の ports / volumes / environment を変えたなら、まず up。
docker compose up -d
反映が怪しければ recreate。
docker compose up -d --force-recreate
そして、build したのに反映されない場合は、volume で上書きされていないか確認する。
自分の場合、何となく「Docker Compose で変更したら build」と考えていましたが、実際には変更内容によって必要な操作が違いました。
特に見るべきなのはこの3つです。
- Dockerfile の変更か
- compose の起動設定変更か
- volume で上書きされる場所か
ここを分けるだけで、build したのに反映されない や また build が走る 系の混乱はかなり減ります。