1行の変更に4分
あるチームが、通販サイトのコードを1行だけ変えました。ビルドに4分かかります。ライブラリをすべてダウンロードし直すからです。
別のチームは同じ1行を変えて、1秒待つだけです。どちらもビルドのファイルを書きました。手順を書く順番が違っただけです。
このレッスンのゴール
メモ
Dockerfile を書き、変更のあとにやり直される手順を言うことができる。
大事な言葉
| ことば | いみ |
|---|---|
| Dockerfile | イメージを作る手順を書いたテキストファイル |
| ベースイメージ | ビルドの出発点になるイメージ |
| レイヤー | ビルドの1手順の結果を保存したもの |
| キャッシュ | ビルドが再利用する、保存済みのレイヤー |
| ビルド | 手順を実行してイメージを作ること |
学生が入力するセルは、このプレビューでは空白です。
ラボにできないこと
メモ
ラボの docker は、イメージのビルドも取得も断ります。ビルドはマシン上で権限のある手順を実行するからです。このレッスンの Dockerfile は私たちのマシンでビルドしました。あなたは読み、イメージがコンテナに残すものを見て、課題で自分のファイルを確かめます。実際にビルドするには、自分のマシンを使います。
Dockerfile は手順のリスト
各行は命令の言葉で始まります。FROM はベースイメージを指します。COPY はファイルを持ち込みます。RUN はビルド中にコマンドを実行します。CMD はコンテナの起動時に動かすものを決めます。
Docker は上から順に行を読みます。小さな通販サイトをこう書きます。
小さな Python サイトの Dockerfile
FROM python:3.12-alpine
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
開始フォルダ(WORKDIR が決める)
docker inspect --format '{{.Config.WorkingDir}}' cacheここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
web を止める信号(STOPSIGNAL)
docker inspect --format '{{.Config.StopSignal}}' webここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
例: 各命令が残すもの
| 命令 | ビルドでの働き | あとで見える場所 |
|---|---|---|
| FROM | ベースイメージから始める | Config.Image がイメージを示す |
| WORKDIR | 以降の手順のフォルダを決める | Config.WorkingDir。cache は /data |
| EXPOSE | プログラムが使う入り口を示す | Config.ExposedPorts。web は 80/tcp |
| STOPSIGNAL | プログラムに止まるよう頼む方法を示す | Config.StopSignal。web は SIGQUIT |
| COPY と RUN | ファイルを足し、コマンドを実行する | それぞれ新しいレイヤー |
学生が入力するセルは、このプレビューでは空白です。
手順ごとにレイヤーができる
ビルドは、各手順の結果をレイヤーとして保存します。レイヤーは積み重なり、イメージはその全体です。レイヤーは、できたあと変わりません。
コンテナは、書き込むための薄いレイヤーを一番上に足します。docker diff は、その一番上のレイヤーの中身を並べます。
例: サイトのイメージのレイヤー
| 手順 | 試験用マシンでの大きさ |
|---|---|
| ベースイメージ python:3.12-alpine | 一番大きいレイヤーで約 48 MB |
| WORKDIR /app | 8 kB |
| COPY requirements.txt . | 12 kB |
| RUN pip install ... | 10.6 MB |
| COPY app.py . | 12 kB |
| CMD ["python", "app.py"] | 0 B |
学生が入力するセルは、このプレビューでは空白です。
web の中にファイルを書く
docker exec web touch /tmp/layer-demo.txtここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
一番上のレイヤーで見つける
docker diff web | grep layer-demoここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
上が変わらなければ再利用する
Docker は手順を実行する前に、1つ確かめます。前回と同じ手順で、同じファイルで、上のすべてが同じだったか。そうなら、保存したレイヤーを再利用します。これがキャッシュです。
最初に違った手順はやり直しです。それ以降のすべてもやり直しです。変わりにくいものを上に置きます。
順序1: 最初にすべてコピーする
FROM python:3.12-alpine
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
CMD ["python", "app.py"]
例: app.py を直して、もう一度ビルド
| 手順 | 順序1 | 順序2(上の最初の Dockerfile) |
|---|---|---|
| WORKDIR /app | キャッシュ | キャッシュ |
| COPY requirements.txt . | この順序にはない | キャッシュ |
| COPY . . | やり直し | この順序にはない |
| RUN pip install ... | やり直し、11秒 | キャッシュ |
| COPY app.py . | この順序にはない | やり直し、1秒未満 |
学生が入力するセルは、このプレビューでは空白です。
よくある間違い
注意
Docker は直した行だけをやり直す、と考える人がいます。やり直すのは、その手順とそれ以降のすべてです。先にライブラリの一覧のファイルをコピーしてインストールし、そのあと自分のコードをコピーします。すると遅い手順はキャッシュに残ります。
もう一歩先へ
自分の小さなサイトの Dockerfile を書きましょう。nginx:1.27-alpine から始め、index.html を1つだけ /usr/share/nginx/html にコピーし、ほかは足しません。
Docker のあるマシンで、2回ビルドします。2回目は、どの手順にも CACHED と出るはずです。