T-CREATOR

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

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

Dockerを学ぶうえで避けて通れないのがDockerfileの理解です。

このファイルは、アプリケーションをコンテナ化する際の「設計図」のような役割を持っています。
しかし、初めて書くときは「FROMって何?」「RUNってどう使うの?」と戸惑うことも多いかと思います。

そこで本記事では、Dockerfileの基本構文と代表的な命令について、豊富なサンプルコードとともに詳しく解説いたします。

公式ドキュメントも交えながら、実践的な内容に落とし込んでおりますので、ぜひ手を動かしながらお読みください。

ベースイメージの指定

Dockerfileを書くうえで、最初に登場するのが FROM 命令です。

これは「どのイメージをベースとして使うか」を指定する命令で、Dockerfileの出発点となります。

DockerfileFROM node:20-alpine

上記のように記述することで、Node.js 20がインストールされた軽量なAlpine Linuxをベースにできます。

他にも以下のような指定が可能です:

命令意味
FROM ubuntu:22.04Ubuntu 22.04ベース
FROM python:3.11-slimPython 3.11の軽量版ベース
FROM nginx:stable-alpineNginxの安定版の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 系イメージが基本
マルチステージビルドでビルド環境と実行環境を分離依存を最小限に抑える
キャッシュ活用のため、順序を工夫COPYRUN installCOPY . の順番が理想
--no-cache などでキャッシュ汚染を防止apk, apt, pip などでのインストール時に有効
CMDENTRYPOINT の役割を明確に分ける柔軟な実行と確実な動作を両立
.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

chmodchown を使ってファイルのアクセス権を適切に調整しましょう。

DockerfileRUN chown -R appuser:appuser /app

おすすめ学習リソースまとめ

Dockerfileをさらに深く学ぶための学習リソースをご紹介します。

まとめ

Dockerfileは、アプリケーションのビルドと運用を効率化するために不可欠なスキルです。

最初は難しく感じるかもしれませんが、基本命令を覚え、構文の意味と使い方を理解していけば、必ず使いこなせるようになります。

今回ご紹介した命令やベストプラクティスをベースに、さまざまなプロジェクトでのDocker活用をぜひ実践してみてください。

正しいDockerfileの記述が、アプリケーションのパフォーマンス、セキュリティ、保守性のすべてを向上させる近道となるはずです。

記事Article

もっと見る