1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Docker Composeでbuildしたのに反映されない・何度もbuildが走る時の切り分けメモ

1
Posted at

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

です。

例えば以下を変えた場合です。

  • FROM
  • RUN apt-get install ...
  • COPY
  • CMD
  • ARG
  • image に含める設定ファイル
  • package.jsoncomposer.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 が走る 系の混乱はかなり減ります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?