こんにちは、かつコーチです。
docker pull で公式イメージを使うだけなら簡単なのですが、自分のアプリケーション用のイメージを作ろうとすると、多くの人が最初につまずくのがDockerfileです。
「命令がたくさんあってどれから書けばいいかわからない」「書いたはいいけどビルドが通らない」という声をよく聞きます。
この記事では、Dockerfileとは何かという基本の考え方から、最小構成のDockerfileを実際に書いてビルドするところまでを、手順に沿って解説します。
Linux基礎編・シェルスクリプト編、そしてDockerの基本操作(run・ps・images)は理解している前提で進めます。
Dockerfileとは?
レシピに例えると分かりやすい
Dockerfile(イメージの作り方を記述したテキストファイルです)は、料理でいうレシピに例えるとイメージしやすいです。
レシピには「材料はこれを使う」「この順番で調理する」という手順が書かれています。
Dockerfileも同じで、「どのOS・言語環境をベースにするか」「どのファイルを配置するか」「起動時に何を実行するか」という手順を順番に記述します。
このレシピ(Dockerfile)を元に docker build すると、完成品であるイメージ(コンテナの設計図)が出来上がります。
なぜDockerfileが必要なのか
イメージは docker commit でコンテナから直接作ることもできます。
ただしこの方法だと、「どんな手順でそのイメージができたのか」が誰にもわからなくなってしまいます。
Dockerfileにテキストとして手順を残しておけば、Gitで管理できますし、同僚が同じ環境を再現することも、半年後の自分が「なぜこの設定にしたか」を思い出すことも簡単になります。
再現性と共有のしやすさこそが、Dockerfileを使う一番の理由です。
基本の書き方・実装手順
最小構成のDockerfileを書いてみる
まずは、Node.jsのアプリケーションを動かす最小構成のDockerfileを見てみましょう。
# Dockerfile
FROM node:20-slim
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["node", "index.js"]
上から順に「ベースイメージを指定する」「作業ディレクトリを決める」「必要なファイルを配置してコマンドを実行する」「起動時のコマンドを決める」という流れになっています。
各命令の詳しい役割は次回の記事で扱うので、ここでは「上から順番に実行される手順書」というイメージだけ持っておいてください。
ビルドしてイメージを作る(docker build)
Dockerfileを書いたら、同じディレクトリで以下を実行します。
docker build -t my-node-app:1.0 .
-t オプションでイメージに名前とタグを付け、末尾の . でビルドコンテキスト(Dockerfileや関連ファイルが置かれているディレクトリ)を指定します。
ビルドが完了したら、docker images で作成されたイメージが確認できます。
docker images
つまずきやすい設定・注意点
Dockerfileを書くときは、.dockerignore(イメージに含めたくないファイルを指定する設定ファイルです)も一緒に用意しておくことをおすすめします。
# .dockerignore
node_modules
.git
*.log
.gitignore に似た書き方で、node_modules のような巨大なディレクトリや、.git のような不要なファイルをビルドコンテキストから除外できます。
これを忘れると、ビルドコンテキストの送信に時間がかかったり、意図しないファイルがイメージに混入したりします。
よくあるつまずきポイント・エラー対処
COPYの順序でキャッシュが毎回効かない
実際に私が経験したつまずきが、Dockerfileの命令順序によるビルド時間の問題です。
❌ Before:ソースコード全体を先にコピーしてしまう
FROM node:20-slim
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "index.js"]
このDockerfileだと、ソースコードを1行変更するだけで COPY . . の内容が変わったと判定され、そこから下の RUN npm install のキャッシュがすべて無効化されます。
私は最初これに気づかず、コードを1行直すたびに npm install が毎回1分以上かかる状態で作業していて、「Dockerのビルドって遅いものなんだ」と誤解していました。
✅ After:依存関係のインストールとソースコードのコピーを分ける
FROM node:20-slim
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["node", "index.js"]
package.json を先にコピーして npm install を済ませておけば、package.json に変更がない限り、この2行分のキャッシュが再利用されます。
ソースコードだけを直した場合は、COPY . . 以降だけが再実行されるので、ビルド時間が数秒まで短縮できました。
応用・一歩先の使い方
レイヤーキャッシュを意識した命令順序
Dockerfileの各命令はレイヤー(変更の少ないものを上に、変更の多いものを下に書くほどキャッシュが効きやすくなります)として積み重なります。
基本の考え方は「変更頻度が低いものを上、高いものを下」です。
- OS・ランタイムのバージョン(
FROM)はほぼ変わらない → 一番上 - 依存関係の定義ファイル(
package.jsonなど)はたまに変わる → 中間 - ソースコードは頻繁に変わる → 一番下
この順序を意識するだけで、日々の開発でのビルド待ち時間を大きく減らせます。
まとめ
この記事のポイント
- Dockerfileはイメージを作るための手順書で、レシピに例えると理解しやすい
docker build -t 名前:タグ .でDockerfileからイメージをビルドする.dockerignoreで不要なファイルをビルドコンテキストから除外する- 変更頻度の低いものを上、高いものを下に書くとキャッシュが効いてビルドが速くなる
次に読むべき記事
- よく使うDockerfile命令(FROM・COPY・RUN・CMD)
- マルチステージビルドでイメージを軽量化する
タグ: Docker, 中級者向け, Dockerfile