Dockerfileの基本構文の紹介!Dockerfile内でよく使う命令まとめ!

Dockerを学ぶうえで避けて通れないのがDockerfileの理解です。
このファイルは、アプリケーションをコンテナ化する際の「設計図」のような役割を持っています。
しかし、初めて書くときは「FROMって何?」「RUNってどう使うの?」と戸惑うことも多いかと思います。
そこで本記事では、Dockerfileの基本構文と代表的な命令について、豊富なサンプルコードとともに詳しく解説いたします。
公式ドキュメントも交えながら、実践的な内容に落とし込んでおりますので、ぜひ手を動かしながらお読みください。
ベースイメージの指定
Dockerfileを書くうえで、最初に登場するのが FROM
命令です。
これは「どのイメージをベースとして使うか」を指定する命令で、Dockerfileの出発点となります。
DockerfileFROM node:20-alpine
上記のように記述することで、Node.js 20がインストールされた軽量なAlpine Linuxをベースにできます。
他にも以下のような指定が可能です:
命令 | 意味 |
---|---|
FROM ubuntu:22.04 | Ubuntu 22.04ベース |
FROM python:3.11-slim | Python 3.11の軽量版ベース |
FROM nginx:stable-alpine | Nginxの安定版のAlpineイメージ |
詳しくは公式のDocker Hubで各イメージの説明を確認することをおすすめいたします。
参考:https://hub.docker.com/_/node
メタデータの追加
LABEL
命令を使用すると、イメージにメタデータ(作者情報やバージョンなど)を付与できます。
DockerfileLABEL maintainer="yourname@example.com"
LABEL version="1.0"
LABEL description="Node.js API server"
これにより、CI/CDのパイプラインなどで情報を参照しやすくなります。
ファイルやディレクトリのコピー
ホストマシンのファイルをコンテナにコピーする際には COPY
または ADD
を使用します。違いも明確にしておきましょう。
DockerfileCOPY ./src /app/src
ADD ./config.tar.gz /app/config/
命令 | 主な特徴 |
---|---|
COPY | 単純なファイルコピー(推奨) |
ADD | 圧縮ファイルの展開やURL対応も可能(慎重に使用) |
COPYの方が予測可能で安全な動作をするため、基本的にはCOPYを使用することが推奨されています。
参考:https://docs.docker.com/engine/reference/builder/#copy
コマンドの実行
コンテナ内でコマンドを実行するには RUN
命令を使用します。
DockerfileRUN apk add --no-cache git
RUN npm install
複数の命令を1つのRUNにまとめると、イメージのレイヤー数が減り、ビルド時間や容量の削減につながります。
DockerfileRUN apk add --no-cache git && \
npm install && \
npm run build
ただし、複雑になりすぎると可読性が下がるため注意が必要です。
作業ディレクトリの指定
WORKDIR
命令は、以後の命令が実行される作業ディレクトリを指定するものです。
DockerfileWORKDIR /app
COPY . .
RUN npm install
このように記述することで、COPYやRUNのカレントディレクトリが明示され、可読性・保守性が向上します。
環境変数の設定
環境変数をコンテナ内に定義するには ENV
命令を使用します。
DockerfileENV NODE_ENV=production
ENV PORT=3000
これにより、アプリケーションやスクリプトが環境に応じた挙動をしやすくなります。
コンテナ起動時のコマンド定義
コンテナ起動時に実行するコマンドを指定するには、CMD
または ENTRYPOINT
を使います。
DockerfileCMD ["npm", "start"]
CMD
は「デフォルトの起動コマンド」としての位置づけです。
一方で、ENTRYPOINT
は「必ず実行するコマンド」として、より強制力があります。
DockerfileENTRYPOINT ["node", "server.js"]
両者を組み合わせることで、柔軟な起動方法が可能となります:
DockerfileENTRYPOINT ["node"]
CMD ["server.js"]
この場合、docker run myapp app.js
と実行すると、node app.js
が実行されることになります。
詳しくはこちら:https://docs.docker.com/engine/reference/builder/#cmd
ポートの公開
アプリケーションが使用するポート番号を指定するには EXPOSE
命令を使います。
DockerfileEXPOSE 3000
これはあくまで「このポートを使います」というドキュメント的な宣言であり、実際のポート公開には -p
オプションが必要です:
Dockerfiledocker run -p 3000:3000 myapp
キャッシュ最適化のための順序
Dockerはレイヤーごとにキャッシュを行います。そのため、変更の頻度が高いものほど後ろに書くのが鉄則です。
良い例:
DockerfileCOPY package.json .
RUN npm install
COPY . .
悪い例:
DockerfileCOPY . .
RUN npm install
このようにしておくと、package.json
に変更がない限り、npm install
がキャッシュから再利用され、ビルド時間を短縮できます。
シェル形式とExec形式の違い
RUN や CMD では以下の2種類の書き方があります。
シェル形式(Shell Form)
DockerfileRUN npm install
CMD npm start
これは /bin/sh -c
を通じてコマンドを実行する形式です。環境変数展開などに対応しています。
Exec形式(JSON Form)
DockerfileRUN ["npm", "install"]
CMD ["npm", "start"]
こちらはエントリポイントとして直接実行されるため、意図したとおりに動きやすく、特に ENTRYPOINT
ではこちらを使うことが推奨されています。
詳しくはこちら:https://docs.docker.com/engine/reference/builder/#exec-form-entrypoint-example
マルチステージビルドによる軽量化
Dockerfileが複雑になると、ビルドされたイメージが巨大化してしまうことがあります。
この問題を解決するために、Dockerは マルチステージビルド をサポートしています。
マルチステージビルドでは、ビルド専用のステージと実行専用のステージを分けることで、不要な依存を最終イメージに含めないようにできます。
以下はNode.jsアプリの例です:
Dockerfile# ステージ1: ビルド用
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# ステージ2: 実行用
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
この方法により、開発ツールや一時ファイルなどを除外でき、セキュアかつ軽量なコンテナを構築できます。
参考:https://docs.docker.com/build/building/multi-stage/
.dockerignore の活用
Dockerfile
とセットで活用したいのが .dockerignore
ファイルです。
これは .gitignore
と同様の構文で、ビルドコンテキストに含めたくないファイルを指定します。
dockerignorenode_modules
dist
*.log
.env
ビルドに不要なファイルを除外することで、ビルド時間の短縮やイメージサイズの削減につながります。
参考:https://docs.docker.com/engine/reference/builder/#dockerignore-file
よく使われるユースケース別テンプレート
以下に、言語やフレームワーク別のDockerfileテンプレートをいくつかご紹介します。
Node.js + TypeScript
DockerfileFROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
Python (Flask)
DockerfileFROM python:3.11-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV FLASK_APP=main.py
CMD ["flask", "run", "--host=0.0.0.0"]
Go
DockerfileFROM golang:1.20-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o app
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/app .
CMD ["./app"]
セキュリティ面での注意点と対策
Dockerfileはビルドするだけでなく、セキュリティにも直結する設計書です。以下の点にご注意ください。
1. root権限での実行を避ける
多くの公式イメージはデフォルトで root
ユーザーです。
そのままアプリを実行すると、万一侵入された際の影響が大きくなります。
以下のように USER
命令で非rootユーザーを使うのが推奨されます。
DockerfileRUN adduser -D appuser
USER appuser
2. イメージのサイズを減らす
不要な依存や一時ファイルが含まれていると、攻撃対象が広がります。
Alpine Linuxベースや、マルチステージビルドを活用しましょう。
3. セキュリティスキャンを活用
docker scan
コマンドを使うことで、イメージに脆弱性がないか簡易チェックが可能です。
bash$ docker scan myapp
さらに詳細な診断には Snyk などのツールもおすすめです。
ベストプラクティスまとめ
以下に、Dockerfileを記述するうえで押さえておきたいポイントをまとめます。
ベストプラクティス | 解説 |
---|---|
小さいベースイメージを選ぶ | alpine , slim 系イメージが基本 |
マルチステージビルドでビルド環境と実行環境を分離 | 依存を最小限に抑える |
キャッシュ活用のため、順序を工夫 | COPY → RUN install → COPY . の順番が理想 |
--no-cache などでキャッシュ汚染を防止 | apk , apt , pip などでのインストール時に有効 |
CMD と ENTRYPOINT の役割を明確に分ける | 柔軟な実行と確実な動作を両立 |
.dockerignore を正しく設定 | サイズ減、速度向上、セキュリティ向上 |
環境変数・秘密情報は直接書かずENVで定義 | .env + docker-compose などの併用が望ましい |
よくあるエラーと対処法
Dockerfile初心者が遭遇しやすいエラーとその対策をいくつか紹介いたします。
COPYに失敗する(ファイルが見つからない)
DockerfileCOPY failed: stat /src/package.json: no such file or directory
→ Dockerfile
からの相対パスが正しいか、COPY
の順序が正しいか確認します。
RUNの実行が失敗する
DockerfileRUN npm install
npm ERR! missing script: install
→ package.json
が正しくコピーされていない可能性があります。COPY
の前後を確認してください。
権限エラー
Permission denied
→ chmod
や chown
を使ってファイルのアクセス権を適切に調整しましょう。
DockerfileRUN chown -R appuser:appuser /app
おすすめ学習リソースまとめ
Dockerfileをさらに深く学ぶための学習リソースをご紹介します。
-
公式ドキュメント(Builder)
https://docs.docker.com/engine/reference/builder/ -
Dockerのベストプラクティス集
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ -
Play with Docker(無料オンライン環境)
https://labs.play-with-docker.com/ -
Docker Hubでのイメージ検索
https://hub.docker.com/ -
Katacoda(対話型チュートリアル)※要アカウント
https://www.katacoda.com/courses/docker
まとめ
Dockerfileは、アプリケーションのビルドと運用を効率化するために不可欠なスキルです。
最初は難しく感じるかもしれませんが、基本命令を覚え、構文の意味と使い方を理解していけば、必ず使いこなせるようになります。
今回ご紹介した命令やベストプラクティスをベースに、さまざまなプロジェクトでのDocker活用をぜひ実践してみてください。
正しいDockerfileの記述が、アプリケーションのパフォーマンス、セキュリティ、保守性のすべてを向上させる近道となるはずです。
記事Article
もっと見る- article
React Suspenseを使う際に避けたいアンチパターン5選と解決策について紹介
- article
React SuspenseとServer Componentsの融合:クライアントとサーバの役割分担
- article
Suspense + useTransitionで滑らかなUXを実現するやり方を紹介
- article
React Suspenseでデータフェッチ!fetchでは動かない理由と正しい書き方について紹介
- article
React 18のSuspense完全対応ガイド:並列レンダリング時代の新常識
- article
Suspense × lazyで始めるコード分割:Reactアプリの初歩的最適化