2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dockerfileが呪文に見える人へ:Nginxを“1ファイル差し替え”してレイヤーとキャッシュを体感する

Posted at

Dockerは触ったことあるけど、Dockerfileを見ると「急によくわからない」…となる人向けの記事です。
今日は Dockerfileを最小構成で書いて、自分のイメージを docker build で作り、docker run で動かすところまでを手でやります。ついでに、2回目のビルドで キャッシュ(CACHED) も体感します。

TL;DR

  • Dockerfileの最低限(FROM / COPY)が読める
  • docker builddocker run の流れで「自作イメージ」を起動できる
  • “Dockerfileは上からレイヤーが積まれる” と “CACHEDの意味” が腹落ちする

これから何をするのか(全体像)

まずは、これを頭に置いてからコマンドに入ります。

(ローカルPC)
  ├─ Dockerfile   … イメージの設計図(上から順に命令)
  └─ index.html   … Nginxで配るHTML(これを差し替える)

        │ docker build
        ▼
  [Docker Image]  … “テンプレ”みたいなもの(レイヤーの集合)
        │ docker run
        ▼
 [Container]      … 実際に動く実体(プロセス)
        │ -p 8080:80
        ▼
   http://localhost:8080 で表示確認

この後やることはシンプルで、

  1. index.html を用意
  2. Dockerfile で「Nginxの中の既定ページを差し替える」
  3. docker build でイメージを作る
  4. docker run で起動してブラウザで確認
  5. HTMLを1文字変えて もう一回 build してキャッシュを観察

という流れです。

前提(環境)

  • Dockerが動くこと(Docker Desktopなど)
  • 端末で docker --version が通ること

なぜDockerfileが必要?(docker run だけじゃダメ?)

結論から言うと、Dockerfileは「ちゃんと動いた」を 再現できる形で残すために必要です。

docker run は “起動” には強いんですが、次みたいな瞬間に困りがちです。

  • コンテナの中で手作業した変更が、次回起動で消える
    例:docker exec でファイルを編集した/パッケージを入れた → コンテナを作り直したら元通り
  • 同じ環境をもう一回作ろうとすると、記憶と勘に頼る
    「あれ、どのコマンド打ったっけ?」が起きる
  • チームや未来の自分に渡せない
    “動いた”の共有が口頭やスクショになる

Dockerfileがあると、これが一気に楽になります。

  • 再現性:誰がいつ作っても同じイメージを作れる(「動く状態」を保存できる)
  • 共有:コードとしてレビューできる/チームに配れる/CIで自動ビルドできる
  • 変更に強い:差分がDockerfileに残るから、原因調査もしやすい

今回のハンズオンは「Dockerfileがあると何が嬉しいか」を最短で体感するために、Nginxのページ差し替えを題材にします。

ハンズオン:最小Dockerfileで “動いた!” を作る

1) 作業フォルダを作る

mkdir dockerfile-hands-on
cd dockerfile-hands-on

完成形はこういうファイル構成になります。

dockerfile-hands-on/
  ├─ Dockerfile
  └─ index.html

2) 配信するHTMLを用意する(index.html)

Nginxで配るページを自分のHTMLにします。

cat > index.html << 'EOF'
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>Dockerfile Hands-on</title>
  </head>
  <body>
    <h1>Hello from my Docker image!</h1>
    <p>index.html を COPY で差し替えました。</p>
  </body>
</html>
EOF

3) Dockerfileを書く(今回は2命令だけ)

ここが今日の主役です。やることは「Nginxを土台にして、既定ページを差し替える」だけ。

cat > Dockerfile << 'EOF'
FROM nginx:1.27-alpine
COPY index.html /usr/share/nginx/html/index.html
EOF

ここでいったん意味を確認

  • FROM ...:ベースとなるイメージを選ぶ(ここではNginx)

  • COPY ...:ローカルのファイルをイメージ内にコピーする

    • Nginxのデフォルト配信先は /usr/share/nginx/html/ なので、そこへ上書きしています

nginx:1.27-alpine は例です。ポイントは タグを固定すること(後で“罠”として触れます)。

4) docker build でイメージを作る

ここで “Dockerfileがイメージに変わる” 体験をします。

Dockerfile(設計図) + index.html(素材)
            │
            └─ docker build
                    │
                    ▼
              Docker Image(完成品)

実行:

docker build -t my-nginx:1 .

-t my-nginx:1 は「このイメージに名前(タグ)を付ける」オプションです。
最後の .ビルド対象(Dockerfileやindex.htmlが置いてある場所) を指します。

ビルドログは環境で多少違いますが、雰囲気はこんな感じです。

  • FROM ... のステップ
  • COPY ... のステップ
  • 最後に Successfully built ... / Successfully tagged ...

5) docker run で起動してブラウザで見る

次は “イメージを実体(コンテナ)として動かす” パートです。

Docker Image(テンプレ)
        │ docker run
        ▼
Container(動いてる実体)───(ポート転送)──▶ localhost:8080

実行:

docker run --name my-nginx -p 8080:80 my-nginx:1
  • --name my-nginx:コンテナに名前を付ける(後で触りやすい)
  • -p 8080:80:PCの8080番 → コンテナの80番(Nginx)へつなぐ

ブラウザで開きます:

  • http://localhost:8080

さっきの Hello from my Docker image! が表示されていれば成功です。
(止めるときは、このターミナルで Ctrl + C

寄り道:2回目の build で「キャッシュ」を体感する

ここからがA+Bの“混ぜどころ”です。
やることは index.htmlを1文字変えて、もう一回 docker build するだけ。

6) index.html をちょっとだけ変更する

例えば見出しを変えます。

sed -i '' 's/Hello from my Docker image!/Hello again (cache test)!/' index.html 2>/dev/null || \
sed -i 's/Hello from my Docker image!/Hello again (cache test)!/' index.html

(macの sed とLinuxの sed の差を吸収するために少しだけ工夫してます。気にしなくてOKです)

7) もう一度 docker build する(ログの “CACHED” を探す)

docker build -t my-nginx:1 .

ここで注目してほしいのが、ビルドログです。
多くの環境では、どこかに CACHED が出ます。

なぜこうなる?(超ざっくり)

Dockerfileは 上から順に実行されて、各行ごとに“レイヤー”として積まれます

Layer 1: FROM nginx:...
Layer 2: COPY index.html ...

今回、変えたのは index.html なので、

  • FROM は変わらない → そのレイヤーは再利用(キャッシュ)
  • COPY はファイルの中身が変わった → そのレイヤーは作り直し

という挙動になります。

「Dockerfileは上から読むだけで、何が変わるとどこが作り直されるか想像できる」
ここが分かると、Dockerfileが一気に怖くなくなります。

なぜキャッシュがあると嬉しい?(“待ち時間” を減らすため)

Dockerを触っていると、意外と多いのがこのループです。

少し変える → build → run → 確認 → また少し変える

このループで毎回フルでビルドが走ると、待ち時間が地味に効いてきます。
特に、開発や学習では “小さな変更を何回も試す” ので、ビルドが遅いとテンポが落ちて理解も進みにくい。

Dockerのキャッシュが効くと、変わっていない手順(レイヤー)は再利用されて、変わった部分だけ作り直します。

  • 嬉しいこと1:反復が速くなる(小さく変えてすぐ試せる)
  • 嬉しいこと2:CIでも速くなる(毎回ゼロからやり直しになりにくい)
  • 嬉しいこと3:Dockerfileを読むコツになる
    「どこが変わると、どこから作り直しになるか」を想像できるようになる

今回の例だと、index.html だけ変えるので、FROM は再利用されて、COPY だけが作り直される…という挙動になります。

レイヤーを“覗く”:docker image history で確認する

見える化するとさらに安心できます。

docker image history my-nginx:1

出力は環境依存ですが、だいたい

  • nginx を土台にしたレイヤー
  • COPY index.html ... に対応するレイヤー

のように並びます。

ここでやりたいことは「細部の理解」ではなく、感覚として

  • Dockerfileの1行が、何かしらの“差分(レイヤー)”を生む
  • その差分が積み重なってイメージになる

と掴むことです。

初心者が踏みがちな罠(最小だけ)

罠1:latest に頼ると、ある日突然ズレる

FROM nginx:latest は便利ですが、いつの間にか中身が変わる可能性があります。
学習中ほど「昨日動いたのに今日は動かない」を避けたいので、まずは タグ固定が安全です。

罠2:docker build の最後の . を雑にすると事故る

docker build -t ... ..ビルドコンテキスト(Dockerに渡す範囲)です。
巨大なフォルダでやると不要ファイルまで含まれて遅くなったり、意図せず秘密情報を含める事故が起きます。

今回みたいに、専用フォルダを切るのが正解です。

罠3:ポートが開かない(-p を忘れる)

Nginxはコンテナ内で80番で待っています。
PCから見るには -p 8080:80 のようなポート転送が必要です。

お片付け(任意)

コンテナを消したいとき:

docker rm -f my-nginx

イメージを消したいとき:

docker rmi my-nginx:1

まとめ(before → after)

  • Dockerfileが「呪文」から「上から読める設計図」になった
  • docker build でイメージを作り、docker run で動かせた
  • 2回目のビルドで CACHED を見て、「どの行が作り直されるか」をレイヤー視点で説明できるようになった

Dockerfileは、覚える命令を増やすより先に “レイヤーとして読む” だけで理解が進みます。今日の2行(FROM / COPY)が読めたなら、もう怖さはだいぶ減ってるはずです。

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?