【Docker攻略】docker buildでDockerfileを正しく指定する完全ガイド|開発・本番別の使い分け

docker-build-dockerfile その他
記事内に広告が含まれています。

Dockerでアプリケーションを構築していると、「開発環境と本番環境で別々のDockerfileを使いたい」「docker buildで特定のDockerfileを指定したい」といった場面に必ず出会います。特にチーム開発やCI/CD環境では、複数のDockerfileを適切に管理できていないと「意図しないファイルでビルドされてしまう」「エラーでビルドが通らない」といったトラブルにつながりやすいのが現実です。また、パスの指定ミスやビルドコンテキストの理解不足が原因で、ファイルがコピーされなかったり、不要なファイルまで含まれてしまったりすることもあります。つまり、Dockerfileの指定方法や運用ルールを正しく理解することは、開発の効率化だけでなくトラブル防止のためにも欠かせないスキルといえます。

この記事では、docker buildコマンドでのDockerfile指定方法から、複数のDockerfileを使い分ける運用テクニック、さらに品質を高めるための最適化ポイントまで体系的に解説します。基礎を押さえたい方はもちろん、実務で運用に悩んでいる方にも役立つ内容になっています。

この記事を読んでわかること

  • docker build -fオプションを使ってDockerfileを指定する正しい方法と具体例
  • Dockerfile.devDockerfile.prodを環境ごとに切り替えて使う方法
  • 相対パス・絶対パスを指定する際の注意点とエラー回避のコツ
  • 複数のDockerfileを効率よく管理するための命名規則とディレクトリ構成のベストプラクティス
  • docker-compose.ymlでDockerfileを指定する方法と実際の記述例
  • Dockerfile記述の最適化(ENV、CMD、COPY、.dockerignoreなど)の具体的な使い方
  • キャッシュの活用やセキュリティを意識したDockerfileの改善方法
  • よくあるエラーとその対処法を押さえ、トラブルシューティングの力を身につける方法

Dockerfileの指定方法をしっかり理解すれば、プロジェクトの再現性や運用効率が格段に向上します。ぜひこの機会に基本から応用まで整理して、日々の開発に役立ててください。

Docker buildでDockerfileを指定する正しい方法

Dockerでイメージをビルドする際、デフォルトでは現在のディレクトリにあるDockerfileという名前のファイルが使用されます。しかし、実際の開発現場では複数の環境に応じて異なるDockerfileを使い分ける必要があります。ここでは、docker buildコマンドで特定のDockerfileを指定する方法を詳しく解説します。

Docker: コンテナー アプリケーション開発の加速
Docker は、開発者がコンテナー アプリケーションを構築、共有、実行できるように設計されたプラットフォームです。面倒なセットアップは私たちが行うので、あなたはコードに集中できます。

docker build -fオプションの正しい使い方と構文例

  • fオプション(または-fileオプション)を使用することで、任意の名前・場所にあるDockerfileを指定できます。基本的な構文は以下の通りです。
docker build -f <Dockerfileのパス> <ビルドコンテキストのパス>

具体的な例を見てみましょう:

# 現在のディレクトリにあるDockerfile.prodを使用してビルド
docker build -f Dockerfile.prod -t myapp:prod .

# dockerディレクトリ内のDockerfile.devを使用してビルド
docker build -f docker/Dockerfile.dev -t myapp:dev .

# イメージ名とタグを同時に指定する場合
docker build -f Dockerfile.test -t myapp:test --build-arg ENV=testing .

重要なポイントは、-fオプションの後にDockerfileのパスを指定し、最後にビルドコンテキスト(通常は.で現在のディレクトリ)を指定することです。この順序を間違えるとエラーになるので注意してください。

Dockerfile.devやDockerfile.prodを指定する例

開発環境と本番環境で異なる設定を使い分ける際の実践例を紹介します。

まず、開発用のDockerfileを作成します:

# Dockerfile.dev
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
# 開発環境では nodemon を使用してホットリロードを有効化
CMD ["npm", "run", "dev"]

次に、本番用のDockerfileを作成します:

# Dockerfile.prod
FROM node:18-alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
# 本番環境では最適化されたビルドを使用
CMD ["npm", "start"]

これらを使い分けるコマンド例:

# 開発環境用イメージをビルド
docker build -f Dockerfile.dev -t myapp:dev .

# 本番環境用イメージをビルド
docker build -f Dockerfile.prod -t myapp:prod .

# 開発コンテナを起動(ボリュームマウントでホットリロード対応)
docker run -d -p 3000:3000 -v $(pwd):/app myapp:dev

# 本番コンテナを起動
docker run -d -p 80:3000 myapp:prod

相対パス・絶対パスでDockerfileを指定する際の注意点

Dockerfileのパス指定では、相対パスと絶対パスの両方が使用できますが、それぞれに注意点があります。

相対パスの場合:

# 現在のディレクトリから見た相対パス
docker build -f ./docker/Dockerfile.dev -t app:dev .
docker build -f ../shared/Dockerfile.common -t app:common .

絶対パスの場合:

# 絶対パスで指定(Linux/macOSの例)
docker build -f /home/user/project/docker/Dockerfile.prod -t app:prod .

# Windowsの場合
docker build -f C:\\Users\\user\\project\\docker\\Dockerfile.prod -t app:prod .

重要な注意点:

ビルドコンテキストとの関係
Dockerfileの場所に関係なく、ビルドコンテキストは最後に指定したパスが基準になります

COPY命令への影響
Dockerfile内のCOPYADD命令は、ビルドコンテキストを基準とした相対パスで記述する必要があります

セキュリティ上の制限
ビルドコンテキスト外のファイルはCOPYできません

# 間違った例:ビルドコンテキスト外のファイルをCOPYしようとする
# Dockerfile内でCOPY ../outside-file.txt ./とすると失敗する
docker build -f docker/Dockerfile -t app .

# 正しい例:必要なファイルをビルドコンテキスト内に配置する
docker build -f docker/Dockerfile -t app ./project-root

複数のDockerfileを使い分ける運用テクニック

実際のプロジェクトでは、開発効率とデプロイメントの柔軟性を両立するために、複数のDockerfileを適切に使い分けることが重要です。

なぜDockerfileを分ける? 開発用と本番用で使い分けるメリット

Dockerfileを環境別に分ける主な理由とメリットは以下の通りです:

1. 開発効率の向上

# Dockerfile.dev - 開発に特化した設定
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
# 開発依存関係も含めてインストール
RUN npm install
COPY . .
# デバッグ用ポートも公開
EXPOSE 3000 9229
# ホットリロード用の設定
ENV NODE_ENV=development
CMD ["npm", "run", "dev"]

2. 本番環境の最適化

# Dockerfile.prod - 本番に特化した設定
FROM node:18-alpine as builder
WORKDIR /app
COPY package*.json ./
# 本番依存関係のみインストール
RUN npm ci --only=production && npm cache clean --force

FROM node:18-alpine
WORKDIR /app
# 最小限のファイルのみコピー
COPY --from=builder /app/node_modules ./node_modules
COPY dist/ ./dist/
COPY package.json ./
# セキュリティ向上のため非rootユーザーで実行
USER node
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", "dist/index.js"]

3. テスト環境の独立

# Dockerfile.test - テスト専用の設定
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
# テスト用のツールとライブラリを追加
RUN npm install --global jest
ENV NODE_ENV=test
CMD ["npm", "test"]

これらの使い分けにより、各環境に最適化されたイメージを作成でき、セキュリティ向上、パフォーマンス最適化、開発効率向上を同時に実現できます。

Dockerfileの命名規則とディレクトリ構成のベストプラクティス

効率的なDockerfile管理のためのディレクトリ構成例:

project-root/
├── docker/
│   ├── Dockerfile.dev          # 開発環境用
│   ├── Dockerfile.prod         # 本番環境用
│   ├── Dockerfile.test         # テスト環境用
│   ├── Dockerfile.staging      # ステージング環境用
│   └── nginx/
│       └── Dockerfile.nginx    # nginxプロキシ用
├── docker-compose.yml          # 開発用compose
├── docker-compose.prod.yml     # 本番用compose
├── .dockerignore
├── src/
└── package.json

命名規則のベストプラクティス:

# 環境別の命名
Dockerfile.dev       # 開発環境
Dockerfile.prod      # 本番環境
Dockerfile.test      # テスト環境
Dockerfile.staging   # ステージング環境

# サービス別の命名
Dockerfile.api       # API サーバー用
Dockerfile.web       # Web フロントエンド用
Dockerfile.worker    # バックグラウンドワーカー用
Dockerfile.nginx     # リバースプロキシ用

# 複合的な命名
Dockerfile.api.prod  # 本番API用
Dockerfile.web.dev   # 開発Web用

ビルド時の実行例:

# 環境別ビルド
docker build -f docker/Dockerfile.dev -t myapp:dev .
docker build -f docker/Dockerfile.prod -t myapp:prod .
docker build -f docker/Dockerfile.test -t myapp:test .

# サービス別ビルド
docker build -f docker/Dockerfile.api -t myapp-api:latest .
docker build -f docker/nginx/Dockerfile.nginx -t myapp-nginx:latest .

# タグを使った環境・バージョン管理
docker build -f docker/Dockerfile.prod -t myapp:v1.2.3-prod .
docker build -f docker/Dockerfile.dev -t myapp:latest-dev .

docker-compose.ymlでbuild時にDockerfileを指定する方法と実例

Docker Composeを使用すると、複数のサービスで異なるDockerfileを効率的に管理できます。

基本的なdocker-compose.ymlの例:

version: '3.8'

services:
  # API サービス(開発用)
  api:
    build:
      context: .
      dockerfile: docker/Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
    depends_on:
      - db

  # データベースサービス
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres_data:/var/lib/postgresql/data

  # Nginx リバースプロキシ
  nginx:
    build:
      context: .
      dockerfile: docker/nginx/Dockerfile.nginx
    ports:
      - "80:80"
    depends_on:
      - api

volumes:
  postgres_data:

本番用のdocker-compose.prod.ymlの例:

version: '3.8'

services:
  api:
    build:
      context: .
      dockerfile: docker/Dockerfile.prod
      args:
        - BUILD_ENV=production
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    restart: unless-stopped
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    secrets:
      - db_password
    restart: unless-stopped

  nginx:
    build:
      context: .
      dockerfile: docker/nginx/Dockerfile.nginx
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - api
    restart: unless-stopped

secrets:
  db_password:
    file: ./secrets/db_password.txt

volumes:
  postgres_data:

実行コマンドの例:

# 開発環境の起動
docker-compose up -d

# 本番環境の起動
docker-compose -f docker-compose.prod.yml up -d

# 特定のサービスのみビルド・起動
docker-compose up --build api

# フォースリビルド(キャッシュを無視)
docker-compose build --no-cache api

# 環境変数ファイルを使用した起動
docker-compose --env-file .env.production -f docker-compose.prod.yml up -d

Dockerfile記述の最適化と品質向上のポイント

効率的で保守性の高いDockerfileを作成するための実践的なテクニックを紹介します。

環境変数(ENV)・コメント(#)・CMD命令の正しい使い方

環境変数(ENV)の効果的な活用:

# 環境変数を使った設定の外部化
FROM node:18-alpine

# アプリケーション設定用の環境変数
ENV NODE_ENV=production \\
    APP_PORT=3000 \\
    LOG_LEVEL=info \\
    DATABASE_URL=""

# パッケージマネージャーの設定
ENV NPM_CONFIG_LOGLEVEL=warn \\
    NPM_CONFIG_PROGRESS=false

WORKDIR /app

# 環境変数を使ったポート設定
EXPOSE $APP_PORT

# パッケージファイルをコピーしてからインストール
COPY package*.json ./
RUN npm ci --only=production

# アプリケーションファイルをコピー
COPY . .

# 非rootユーザーでの実行(セキュリティ向上)
RUN addgroup -g 1001 -S nodejs && \\
    adduser -S nextjs -u 1001
USER nextjs

# 環境変数を使った起動設定
CMD ["sh", "-c", "node server.js --port=$APP_PORT"]

わかりやすいコメントの書き方:

# =================================
# Multi-stage build for Node.js app
# =================================

# Stage 1: Dependencies installation
FROM node:18-alpine as dependencies
WORKDIR /app
# パッケージファイルのみコピーして依存関係をインストール
# これによりソースコード変更時のキャッシュ効率が向上
COPY package*.json ./
RUN npm ci --only=production && \\
    # npm キャッシュをクリーンアップしてイメージサイズを削減
    npm cache clean --force

# Stage 2: Build stage
FROM node:18-alpine as builder
WORKDIR /app
COPY package*.json ./
# 開発依存関係も含めてインストール(ビルドに必要)
RUN npm ci
COPY . .
# TypeScript のビルドを実行
RUN npm run build

# Stage 3: Production image
FROM node:18-alpine as production
WORKDIR /app

# 本番環境用の設定
ENV NODE_ENV=production

# セキュリティ:非rootユーザーでの実行
RUN addgroup -g 1001 -S nodejs && \\
    adduser -S nextjs -u 1001

# 本番に必要なファイルのみコピー
COPY --from=dependencies /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./

# ファイルの所有者を変更
RUN chown -R nextjs:nodejs /app
USER nextjs

EXPOSE 3000

# ヘルスチェック用のエンドポイント
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
    CMD curl -f <http://localhost:3000/health> || exit 1

# アプリケーション起動
CMD ["node", "dist/server.js"]

CMDENTRYPOINTの使い分け:

# CMD の例:起動コマンドを完全に上書き可能
FROM alpine:latest
RUN apk add --no-cache curl
CMD ["curl", "--help"]
# 実行例:docker run myimage curl <https://example.com>

# ENTRYPOINT の例:基本コマンドは固定、引数のみ変更可能
FROM alpine:latest
RUN apk add --no-cache curl
ENTRYPOINT ["curl"]
CMD ["--help"]
# 実行例:docker run myimage <https://example.com>

# 組み合わせの例:柔軟性とデフォルト動作を両立
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
ENTRYPOINT ["npm"]
CMD ["start"]
# 実行例:
# docker run myapp               → npm start
# docker run myapp run test     → npm run test
# docker run myapp run build    → npm run build

COPY命令でディレクトリをまとめてコピーする方法と.dockerignoreの活用

効率的なCOPY命令の使い方:

# 悪い例:個別にファイルをコピー(非効率)
COPY package.json ./
COPY package-lock.json ./
COPY tsconfig.json ./
COPY src/ ./src/
COPY public/ ./public/

# 良い例:パターンを活用してまとめてコピー
COPY package*.json tsconfig.json ./
COPY src/ ./src/
COPY public/ ./public/

# より効率的な例:依存関係のインストールとソースコードコピーを分離
# 1. 依存関係ファイルのみコピー(キャッシュ効率向上)
COPY package*.json ./
RUN npm ci --only=production

# 2. その後でソースコードをコピー
COPY . .

.dockerignoreファイルの活用例:

# .dockerignore ファイル

# Version control
.git
.gitignore

# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Build outputs
dist/
build/
coverage/

# Environment files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# IDE and editor files
.vscode/
.idea/
*.swp
*.swo
*~

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Logs
logs/
*.log

# Temporary files
tmp/
temp/

# Test files
*.test.js
**/__tests__/

# Documentation
README.md
docs/

# Docker files
Dockerfile*
docker-compose*.yml
.dockerignore

# CI/CD files
.github/
.gitlab-ci.yml
.travis.yml

COPY命令の詳細な使い方:

FROM node:18-alpine
WORKDIR /app

# 所有者とパーミッションを指定してコピー
COPY --chown=node:node package*.json ./
RUN npm ci --only=production

# 特定のファイルのみを選択してコピー
COPY --chown=node:node src/ ./src/
COPY --chown=node:node public/ ./public/
COPY --chown=node:node *.json *.js ./

# ワイルドカードを使った柔軟なコピー
COPY --chown=node:node config/*.conf ./config/

# マルチステージビルドでのコピー
FROM node:18-alpine as builder
WORKDIR /app
COPY . .
RUN npm run build

FROM nginx:alpine
# 前のステージからビルド済みファイルをコピー
COPY --from=builder /app/dist /usr/share/nginx/html

キャッシュ最適化・セキュリティ対策の実践例

Dockerビルドキャッシュの最適化:

# キャッシュ効率を最大化したDockerfile
FROM node:18-alpine

# 1. システムパッケージの更新とインストール(変更頻度が低い)
RUN apk update && apk add --no-cache \\
    curl \\
    git \\
    && rm -rf /var/cache/apk/*

# 2. アプリケーションユーザーの作成(変更頻度が低い)
RUN addgroup -g 1001 -S nodejs && \\
    adduser -S nextjs -u 1001

WORKDIR /app

# 3. 依存関係ファイルのみ先にコピー(package.jsonが変更された時のみ再実行)
COPY --chown=nextjs:nodejs package*.json ./

# 4. 依存関係のインストール(package.jsonが変更された時のみ再実行)
USER nextjs
RUN npm ci --only=production && \\
    npm cache clean --force

# 5. ソースコードのコピー(最後に実行、変更頻度が最も高い)
COPY --chown=nextjs:nodejs . .

EXPOSE 3000

# ヘルスチェックの設定
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
    CMD curl -f <http://localhost:3000/health> || exit 1

CMD ["npm", "start"]

セキュリティ対策の実装:

# セキュリティ強化されたDockerfile
FROM node:18-alpine

# セキュリティアップデートの適用
RUN apk update && apk upgrade && \\
    apk add --no-cache \\
    dumb-init \\
    curl \\
    && rm -rf /var/cache/apk/*

# 非rootユーザーでの実行
RUN addgroup -g 1001 -S appgroup && \\
    adduser -S appuser -u 1001 -G appgroup

WORKDIR /app

# ファイルの所有者とパーミッションを適切に設定
COPY --chown=appuser:appgroup package*.json ./
USER appuser
RUN npm ci --only=production && \\
    npm cache clean --force

COPY --chown=appuser:appgroup . .

# 不要なパーミッションを除去
RUN chmod -R 755 /app && \\
    find /app -type f -exec chmod 644 {} \\; && \\
    chmod 755 /app/server.js

# セキュリティヘッダーとポート制限
EXPOSE 3000

# プロセス管理用のdumb-initを使用
ENTRYPOINT ["dumb-init", "--"]

# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
    CMD curl -f <http://localhost:3000/health> || exit 1

CMD ["node", "server.js"]

Build Argsを使った設定の外部化:

FROM node:18-alpine

# ビルド時引数の定義
ARG NODE_ENV=production
ARG APP_VERSION=latest
ARG BUILD_DATE
ARG VCS_REF

# メタデータラベルの追加
LABEL maintainer="your-email@example.com" \\
      version="${APP_VERSION}" \\
      build-date="${BUILD_DATE}" \\
      vcs-ref="${VCS_REF}" \\
      description="My Node.js Application"

# 環境変数として設定
ENV NODE_ENV=${NODE_ENV} \\
    APP_VERSION=${APP_VERSION}

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

ビルド実行例:

# Build args を使用したビルド
docker build \\
  --build-arg NODE_ENV=production \\
  --build-arg APP_VERSION=1.0.0 \\
  --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \\
  --build-arg VCS_REF=$(git rev-parse --short HEAD) \\
  -f Dockerfile.prod \\
  -t myapp:1.0.0 .

# キャッシュを使わない完全リビルド
docker build --no-cache -f Dockerfile.prod -t myapp:1.0.0 .

# 特定のターゲットステージまでビルド
docker build --target builder -f Dockerfile.prod -t myapp:builder .

よくある質問(FAQ)

docker build -fでDockerfileを指定してもビルドが失敗します。どのような原因が考えられますか?

最も多い原因は以下の通りです:

1.パスの指定ミス:Dockerfileのパスとビルドコンテキストのパスを確認してください

# 間違い
docker build -f ./docker/Dockerfile.dev

# 正しい(ビルドコンテキストの指定が必要)
docker build -f ./docker/Dockerfile.dev .

2.ビルドコンテキスト外のファイル参照COPY命令でビルドコンテキスト外のファイルを指定している場合

# エラーが発生する例
docker build -f ../docker/Dockerfile .
# Dockerfile内で COPY ../config.txt . を実行すると失敗

3.ファイルの権限問題:Dockerfileに読み取り権限がない場合

# 権限を確認
ls -la Dockerfile.prod
# 必要に応じて権限を変更
chmod 644 Dockerfile.prod

マルチステージビルドを使用している場合、-fオプションでの指定方法は変わりますか?

マルチステージビルドでも-fオプションの使用方法は同じです。ただし、特定のステージのみビルドする場合は--targetオプションを併用します:

# 特定のステージまでビルド
docker build -f Dockerfile.prod --target builder -t myapp:builder .

# 最終ステージまでビルド
docker build -f Dockerfile.prod -t myapp:prod .

Docker Composeで複数のDockerfileを使用する際、環境変数やビルド引数はどのように管理すべきですか?

環境別の設定ファイルと.envファイルを組み合わせて管理することをおすすめします:

# docker-compose.yml
version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: docker/Dockerfile.${ENV:-dev}
      args:
        - NODE_ENV=${NODE_ENV:-development}
        - API_URL=${API_URL}
    environment:
      - DATABASE_URL=${DATABASE_URL}

# .env.development
ENV=dev
NODE_ENV=development
API_URL=http://localhost:3001
DATABASE_URL=postgres://localhost:5432/myapp_dev

# .env.production
ENV=prod
NODE_ENV=production
API_URL=https://api.myapp.com
DATABASE_URL=postgres://prod-db:5432/myapp

Dockerfileを指定してビルドした際、イメージサイズが想定より大きくなります。最適化の方法を教えてください。

イメージサイズ最適化のための具体的な手法:

1.マルチステージビルドの活用

# ビルドステージ
FROM node:18 as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 本番ステージ(軽量なベースイメージを使用)
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

2.不要なファイルの除外

# ビルド前にイメージサイズを確認
docker images myapp

# 最適化後のビルド
docker build -f Dockerfile.optimized -t myapp:optimized .

# サイズ比較
docker images myapp

CI/CDパイプラインでDockerfileを指定してビルドする際のベストプラクティスはありますか?

CI/CDでの実践的なアプローチ:

# GitHub Actions の例
name: Build and Deploy
on:
push:
branches: [main, develop]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Build development image
if: github.ref == 'refs/heads/develop'
run: |
docker build -f docker/Dockerfile.dev -t myapp:dev-${{ github.sha }} .

- name: Build production image
if: github.ref == 'refs/heads/main'
run: |
docker build -f docker/Dockerfile.prod -t myapp:prod-${{ github.sha }} .

- name: Run security scan
run: |
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \\
aquasec/trivy image myapp:prod-${{ github.sha }}

既存のDockerfileを環境別に分割する際の移行戦略を教えてください。

段階的な移行アプローチをおすすめします:

ステップ1:現状の分析と共通部分の特定

# 現在のDockerfileをバックアップ
cp Dockerfile Dockerfile.original

# 共通処理を特定(ベースイメージ、システムパッケージなど)
# 環境固有の処理を特定(依存関係、起動コマンドなど)

ステップ2:テンプレートベースでの分割

# Dockerfile.base(共通テンプレート)
FROM node:18-alpine
RUN apk add --no-cache curl git
WORKDIR /app
COPY package*.json ./

# Dockerfile.dev(開発環境固有の追加)
FROM myapp:base
RUN npm install  # 開発依存関係も含む
COPY . .
CMD ["npm", "run", "dev"]

# Dockerfile.prod(本番環境固有の追加)
FROM myapp:base
RUN npm ci --only=production
COPY . .
CMD ["npm", "start"]

ステップ3:段階的なテスト導入

# 1. 開発環境での検証
docker build -f Dockerfile.dev -t myapp:dev-test .
docker run -d -p 3000:3000 myapp:dev-test

# 2. ステージング環境での検証
docker build -f Dockerfile.staging -t myapp:staging-test .

# 3. 問題なければ本番環境へ適用
docker build -f Dockerfile.prod -t myapp:prod .

ネットワークが制限された環境でDockerfileを使用する場合の注意点はありますか?

オフライン環境やプロキシ環境での対応方法:

1.プロキシ設定の追加

# プロキシ環境用のDockerfile
FROM node:18-alpine

# プロキシ設定(ビルド時引数として受け取り)
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY

ENV HTTP_PROXY=${HTTP_PROXY} \\
    HTTPS_PROXY=${HTTPS_PROXY} \\
    NO_PROXY=${NO_PROXY}

# npm のプロキシ設定
RUN if [ -n "$HTTP_PROXY" ]; then npm config set proxy $HTTP_PROXY; fi && \\
    if [ -n "$HTTPS_PROXY" ]; then npm config set https-proxy $HTTPS_PROXY; fi

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
CMD ["npm", "start"]

# プロキシを指定してビルド
docker build \\
  --build-arg HTTP_PROXY=http://proxy.company.com:8080 \\
  --build-arg HTTPS_PROXY=http://proxy.company.com:8080 \\
  --build-arg NO_PROXY=localhost,127.0.0.1 \\
  -f Dockerfile.proxy \\
  -t myapp:proxy .

2.オフライン用の依存関係事前ダウンロード

# オフライン環境用のDockerfile
FROM node:18-alpine

WORKDIR /app

# 事前にダウンロードした依存関係をコピー
COPY offline-cache/ ./offline-cache/
COPY package*.json ./

# オフラインキャッシュから依存関係をインストール
RUN npm ci --cache ./offline-cache --prefer-offline --no-audit

COPY . .
CMD ["npm", "start"]

まとめ

この記事では、docker buildコマンドで特定のDockerfileを指定する方法から、実際の運用で役立つ高度なテクニックまでを包括的に解説しました。

重要ポイント

  • fオプションの基本docker build -f <Dockerfileのパス> <ビルドコンテキスト>の構文を正確に理解し、パスの指定に注意する
  • 環境別の使い分け:開発・ステージング・本番環境それぞれに最適化されたDockerfileを用意することで、効率性とセキュリティを両立できる
  • 命名規則とディレクトリ構成:一貫した命名規則と整理されたディレクトリ構成により、チーム開発での保守性が大幅に向上する
  • Docker Composeとの連携:複数のサービスで異なるDockerfileを効率的に管理でき、環境切り替えも簡単に行える
  • 最適化とセキュリティ:マルチステージビルド、適切なユーザー権限、キャッシュ戦略により、高品質なイメージを作成できる

実際の開発現場では、これらのテクニックを組み合わせることで、保守性が高く効率的なコンテナ環境を構築できます。まずは小規模なプロジェクトから始めて、段階的に複雑な構成に挑戦していくことをおすすめします。

Dockerfileの指定方法をマスターすることで、より柔軟で効率的なコンテナベースの開発・デプロイメントワークフローを実現できるでしょう。

タイトルとURLをコピーしました