Dockerは現代のソフトウェア開発に欠かせないツールとなり、チームはこれまでにない一貫性と容易さでアプリケーションを構築、リリース、実行できるようになりました。このコンテナ化の魔法の中核を成すのが、Dockerイメージ作成の青写真として機能する、シンプルでありながら強力なスクリプトであるDockerfileです。
効果的なDockerfileビルドプロセスを構築することは、単なる技術的な演習ではありません。開発サイクルの高速化、アプリケーションのフットプリントの小型化とセキュリティ強化、そしてデプロイメントの信頼性向上への道筋となるのです。Dockerを初めて使う方にも、スキルアップを目指す方にも、このガイドは実用的で効率的かつ安全なDockerfileを作成するための基本を解説します。.
Dockerエコシステムを理解する:簡単な復習

Dockerfiles の詳細に入る前に、主要な Docker の概念について簡単に触れておきましょう。
- イメージ:イメージは、コード、ランタイム、ライブラリ、環境変数、設定ファイルなど、ソフトウェアの実行に必要なすべてのものを含む、軽量でスタンドアロンの実行可能パッケージです。イメージは不変のテンプレートです。
- コンテナ:コンテナは、イメージの実行可能なインスタンスです。コンテナは作成、起動、停止、移動、削除することができ、アプリケーションに隔離された環境を提供します。
- Dockerfile:これが今回の焦点です。Dockerfileは、Dockerがイメージを自動的に組み立てるために使用する一連のコマンドを記述したテキストドキュメントです。
- Docker Hub/レジストリ:これらは、コード用の GitHub に似た、Docker イメージを保存および共有するためのリポジトリです。
適切に作成された Dockerfile は、可能な限り軽量で、構築が速く、安全なイメージを作成する
Dockerビルドフラグの説明
- -t myapp:1.0 : このフラグは、イメージに名前 (myapp) とバージョン (1.0) をタグ付けします。タグ付けはバージョン管理に役立ち、特にデプロイやレジストリへのプッシュ時に、後で特定のイメージビルドを参照しやすくなります。
- . (ドット) : これはビルドコンテキストを指します。Docker が Dockerfile やビルド中に必要なその他のファイル(イメージにコピーするファイルなど)を検索するディレクトリです。Docker
はこのディレクトリの内容を圧縮し、Docker デーモンに送信します。ビルドプロセス中は、ビルドコンテキスト内のファイルのみにアクセスできることに注意してください。
基本的なDockerfileの指示:構成要素

最も一般的な指示と、それらを効果的に使用する方法を見てみましょう。.
- から: すべてのDockerfileはFROM命令で始まる必要があります。これは、イメージを構築するベースイメージを指定します。.
- 目的: 開始点を選択します。通常は、オペレーティング システム (Ubuntu:22.04 など) または事前構成されたアプリケーション ランタイム (node:18-alpine など) です。.
- 例: FROM python:3.9-slim
- ベストプラクティス:アプリケーションのニーズを満たす最小限のベースイメージを選択してください。Alpineバージョンはサイズが小さいですが、musl libcを使用しているため、一部のC言語依存パッケージとの互換性に問題が生じる可能性があります。Slimバージョンは、標準的なディストリビューション(Debianなど)のglibcを簡素化したバージョンであり、妥協案として最適です。
- WORKDIR: この設定はwを設定します後続の RUN、CMD、ENTRYPOINT、COPY、および ADD 命令のワーキング ディレクトリ。.
- 目的:後続のファイル操作やコマンド実行のために、イメージ内の現在のディレクトリコンテキストを定義します。ディレクトリが存在しない場合は、Docker によって作成されます。
- 例: WORKDIR /usr/src/app
- ベストプラクティス: WORKDIR には絶対パスを使用してください。WORKDIR を使用してディレクトリを複数回変更する方が、RUN 命令内で cd コマンドを連鎖させるよりも一般的に簡潔です。
- コピー: ビルド コンテキストからイメージのファイル システムにファイルまたはディレクトリをコピーします。.
- 目的:アプリケーション コード、構成ファイル、その他の必要なアセットをイメージに追加します。
- 例:
Dockerfile
WORKDIR /usr/src/app
COPY package.json ./
COPY src/ ./src/
- ベストプラクティス:単純なファイルコピーには、ADDよりもCOPYを推奨します。COPYの方が透過的です。ADDにはURLダウンロードやtar抽出などの追加機能があり、予測しにくい場合があります。ダウンロードと抽出が必要な場合は、明瞭性とセキュリティの観点から、多くの場合、curl、wget、tarとRUNを使用する方が適切です。
- 走る: 現在のイメージの上に新しいレイヤーを作成し、コマンドを実行し、結果をコミットします。ソフトウェアのインストール、ディレクトリの作成、コードのコンパイルなどに使用されます。.
- 目的:パッケージをインストールしたり、ビルド スクリプトを実行したり、構成を設定したりして、イメージのファイルシステムを変更します。
- 例:
Dockerfile
RUN apt-get update && apt-get install -y –no-install-recommends \
nginx \
curl \
&& rm -rf /var/lib/apt/lists/*
- ベストプラクティス:関連するコマンドを && を使用して連結し、同じ RUN 命令内で一時ファイルやパッケージマネージャのキャッシュをクリーンアップします(Debian/Ubuntu の場合は rm -rf /var/lib/apt/lists/*、CentOS/RHEL の場合は yum clean all など)。これにより、各 RUN 命令で新しいレイヤーが作成されるため、レイヤー数が最小限に抑えられ、イメージサイズが縮小されます。
- 環境: ビルド プロセス中 (定義された後) およびイメージからコンテナーを実行するときに使用できる環境変数を設定します。.
- 目的:アプリケーションまたはビルド スクリプトに必要な構成値、パス、または設定を提供します。
- 例:
Dockerファイル
ENV NODE_ENV=production
ENV APP_PORT=3000
- ベストプラクティス:機密性が低い設定データには ENV を使用してください。機密情報には ENV を使用してイメージに焼き込むのではなく、ランタイムインジェクションメソッドを使用してください。
- 議論: Docker ビルド中にユーザーが --build-arg フラグを使用して渡すことができるビルド時変数を定義します。.
- 目的: Dockerfile を変更せずにビルド プロセスのパラメーター化を可能にします。
- 例: Dockerfile
Dockerfile
ARG APP_VERSION=1.0.0
ENV APP_VERSION_ENV=${APP_VERSION}
RUN echo “ビルドバージョン ${APP_VERSION_ENV}”
- ビルドに使うもの: バッシュ docker ビルド – ビルド引数 APP_VERSION=1.2.3 -t myapp.
- 注意:上記のように、明示的に ENV 変数として設定されない限り、ARG 変数は実行中のコンテナーでは使用できません。
- さらす: 実行時にコンテナが指定されたネットワーク ポートをリッスンすることを Docker に通知します。.
- 目的:このドキュメントは主にイメージビルダーとユーザー向けのドキュメントとして機能します。ポートの公開は行いません。
例:
Dockerfile
EXPOSE 8080
- 注: ホストからポートにアクセスできるようにするには、docker run で -p または -P フラグを使用します (例: docker run -p 8080:8080 myimage)。.
- 司令官 そして エントリーポイント: コンテナの起動時に実行されるコマンドを定義します。.
- CMD [“executable”, “param1”, “param2”] :実行中のコンテナのデフォルト設定を指定します。これらのデフォルト設定は、docker run にコマンドを追加することで簡単に上書きできます。複数の CMD を指定した場合、最後のものだけが有効になります。
- ENTRYPOINT [“executable”, “param1”, “param2”] :コンテナを実行可能ファイルとして実行するように設定します。docker run に渡される引数は、ENTRYPOINT コマンドに追加されます。
- 例(典型的なパターン):
Dockerfile
ENTRYPOINT [“python”, “app.py”] # メインコマンド
CMD [“–help”] # docker run で何も指定されていない場合のデフォルト引数
- ベストプラクティス:簡単に上書きできるデフォルトコマンドが必要な場合は、CMDを使用してください。特定の実行ファイルのように動作するイメージを作成するには、ENTRYPOINTを使用します。多くの場合、CMDはデフォルト引数の指定に使用されます。Webアプリケーションの場合、CMD [“npm”, “start”] または CMD [“python”, “manage.py”, “runserver”] が標準です。
最適化された Dockerfile の主なベストプラクティス

機能的なDockerfileを書くことはほんの始まりに過ぎません。最適化することで大きなメリットがもたらされます。.
- ビルド キャッシュを効果的に活用する: Dockerはイメージをレイヤーごとにビルドし、可能であれば以前のビルドのレイヤーを再利用しようとします(キャッシュ)。キャッシュヒットを最大化するには、以下の手順を実行します。
- 変更頻度の低い命令から高い命令へと順序付けます。例えば、頻繁に変更されるアプリケーションのソースコードをコピーする前に
Dockerfile
# Node.js アプリの優れたキャッシュ例
FROM node:18-alpine
WORKDIR /app
COPY package.json package-lock.json ./ # 依存関係の変更頻度が低い
RUN npm ci –omit=dev # パッケージファイルが変更されない場合、このレイヤーはキャッシュされます
COPY . . # ソースコードは頻繁に変更されるため、最後になります
CMD [“node”, “server.js”]
- 画像を小さく保つ: イメージが小さいほど、プル、プッシュ、デプロイが高速になり、攻撃対象領域が縮小されます。.
- 最小限のベースイメージを使用する: Alpine、slim、または distroless バリアントは、完全な OS イメージよりも大幅に小さくなります。
- 同じ RUN レイヤーでクリーンアップ: パッケージをインストールした後、同じRUN命令を使って不要なキャッシュや一時ファイルを削除します。例:
- Debian/Ubuntu: apt-get clean && rm -rf /var/lib/apt/lists/*
- CentOS/RHEL: yum clean allまたはdnf clean all
- アルパイン: rm -rf /var/cache/apk/*
- マルチステージビルドを採用する: これは、特にコンパイルされた言語やビルド ステップのあるアプリケーション (JavaScript フロントエンドなど) の場合に、イメージ サイズを縮小する最も効果的な方法の 1 つです。.
- コンセプト:すべてのビルドツールと開発依存関係を含む1つのステージ(FROMブロック)を使用して、アプリケーションをコンパイル/ビルドします。次に、新しいステージを開始し、COPY–from=を使用します。
… 必要なコンパイル済み成果物のみを - 例(簡略化されたGoアプリケーション):Dockerfile
- コンセプト:すべてのビルドツールと開発依存関係を含む1つのステージ(FROMブロック)を使用して、アプリケーションをコンパイル/ビルドします。次に、新しいステージを開始し、COPY–from=を使用します。
Dockerfile
# ステージ 1: ビルド
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# ステージ 2: ランタイム
FROM debian:bullseye-slim
WORKDIR /app
COPY –from=builder /app/myapp .
CMD [“./myapp”]
- ビルダー ステージには Go SDK がありますが、最終イメージにはコンパイルされたバイナリと最小限の Alpine OS のみが含まれています。.
- セキュリティを優先する:
- 非ルートユーザーとして実行:デフォルトでは、コンテナはルートユーザーとして実行されます。これはセキュリティリスクです。Dockerfileに専用の非特権ユーザーとグループを作成し、USER命令を使用して切り替えてください。Dockerfile
Dockerfile
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# … ファイルをコピーし、appuser:appgroup に chown します …
USER appuser
- 必要なパッケージのみをインストールする:すべてのパッケージは潜在的な脆弱性を秘めています。本番環境イメージにデバッグツールや開発ユーティリティをインストールすることは避けてください(マルチステージビルドを使用してください)。
- シークレットをハードコードしない: Dockerfile(例:環境変数)にパスワード、APIキー、その他のシークレットを配置しないでください。Dockerシークレット、Kubernetesシークレット、または実行時に安全に提供される環境変数などのランタイムインジェクション手法を使用してください。
- .dockerignore を効果的に使用するには、ビルドコンテキストのルート(Dockerfile と同じ階層)に .dockerignore ファイルを作成します。Docker デーモンに送信しないファイルとディレクトリをリストします(例:.git、イメージにインストールされている場合は node_modules、ローカル IDE 設定、*.log)。
- ビルド コンテキストのサイズを縮小し、機密ファイルや不要なファイルがイメージに含まれないようにすることで、 Docker ビルド プロセスを高速化します
基本を超えて:さらなる強化

上記に慣れたら、さらに優れた Dockerfile を作成するために以下を検討してください。
- BuildKit: Dockerの新しいビルドエンジン。多くの場合、デフォルトで有効になっています。優れたパフォーマンス(並列ビルド)、改良されたキャッシュ機能、そしてパッケージマネージャー向けのビルドシークレット(RUN– mount=type=secret、…)やキャッシュマウント(RUN– mount=type=cache、…)といった高度な機能を備えています。BuildKitが有効になっていることを確認するか、DOCKER_BUILDKIT=1で有効化してください。
- Dockerfile の Lint 処理: Hadolint (hadolint Dockerfile) などのツールを使用して、ビルド前に Dockerfile のエラー、スタイル違反、ベスト プラクティスへの準拠を静的に分析します。
よくあるトラブルシューティングのクイックヒント
- COPYまたはADD中に「ファイルが見つかりません」 :ソース パス (ビルド コンテキスト ルートからの相対パス) を再確認し、ファイルが .dockerignore によって除外されていないことを確認します。
- ビルドが遅い場合:キャッシュを最適化するために命令の順序を確認してください。可能な場合はRUNコマンドを組み合わせます。.dockerignoreが包括的であることを確認してください。
- 大きなイメージ:マルチステージビルドを使いましょう!RUNレイヤーでクリーンアップを行いましょう。ベースイメージは最小限に抑えましょう。
DevOps ワークフローにおける Dockerfiles
Dockerfile は、「Infrastructure as Code」の重要な要素です。
- バージョン管理: Dockerfile を常にアプリケーション コードと一緒に Git リポジトリにコミットします。
- CI/CD統合:継続的インテグレーション/継続的デリバリーパイプライン(GitHub Actions、Jenkins、GitLab CIなど)内で、Dockerビルドとイメージプッシュプロセスを自動化します。これにより、一貫性と繰り返し性を確保したビルドとデプロイメントが可能になります。
結論:成功の基盤を築く
効果的なDockerfileを作成することは、開発スピード、運用の信頼性、そしてアプリケーションのセキュリティにおいて大きなメリットをもたらす投資です。基本的な手順を習得し、マルチステージビルドやイメージレイヤーの慎重な管理といったベストプラクティスを実践し、セキュリティを最優先することで、無駄がなく、効率的で、堅牢なDockerイメージを作成できます。.
このガイドはしっかりとした基礎を提供します。Dockerを使い続ける中で、Dockerfileの探求、実験、改良を続けてください。.
Docker と DevOps の実践を向上させる準備はできていますか?
Seahawk Mediaは、コンテナ化、クラウドテクノロジー、そして合理化されたCI/CDパイプラインの可能性を最大限に活用できるよう、企業を支援することに特化しています。アプリケーションのデプロイメントの最適化、セキュリティの強化、開発ライフサイクルの加速など、お客様のご要望に専門チームがお応えします。