PHPアプリケーションのコンテナイメージを作成する際、ビルドに必要なツール(Composer、各種コンパイラなど)をすべて含めてしまうと、イメージが肥大化し、セキュリティリスクも増大します。
この課題を解決するのが、コンテナビルドの効率を最大化する技術、マルチステージビルドです。
マルチステージビルドとは?
マルチステージビルドとは、一つのDockerfile内で複数のFROM命令(ステージ)を定義し、最終的なイメージにデプロイに必要なファイルだけをコピーする手法です。
役割分担
- ビルドステージ (Build Stage):
- 目的: アプリケーションのビルドと依存関係の解決。
- 使用イメージ: 大きなイメージ(例:
composer:latest、php:8.3-fpmなど)。 - 作業: Composerによる依存パッケージのインストール、フロントエンドアセットのコンパイル、テストの実行などを行います。
- 特徴: このステージは最終的なデプロイには使用されません。
- 最終ステージ (Final Stage):
- 目的: アプリケーションの実行環境の構築。
- 使用イメージ: 軽量なイメージ(例:
php:8.3-fpm-alpine、distrolessなど)。 - 作業: ビルドステージで生成された成果物(例:
vendorディレクトリ、コンパイル済みバイナリ、PHPコード)のみをコピーします。
メリット
- イメージサイズの劇的な削減: ビルドツールやキャッシュ、開発用の依存関係が最終イメージから完全に除外されます。
- セキュリティ向上: 最終イメージが最小限の構成になるため、攻撃対象となる領域が縮小します。
- ビルド時間の短縮: 軽量なイメージを使用することで、プル時間が短くなります。
PHPアプリケーションでのマルチステージビルド
PHPアプリケーションの典型的なマルチステージビルドは、Composerによる依存関係の解決を分離することに焦点を当てます。
Dockerfile
以下のDockerfileは、Composerで依存関係を解決するステージと、それを使ってアプリケーションを実行する最小限のステージに分離しています。
# =============================================# ステージ1:build_stage(依存関係の解決)# =============================================FROM composer:latest AS build_stage WORKDIR /app # 先に依存関係ファイルだけをコピー(キャッシュ効率化のため) COPY composer.json composer.lock ./ # 本番環境用に最適化してインストール# --no-dev: 開発用パッケージを除外# --optimize-autoloader: オートローダーを最適化して高速化RUN composer install \--no-dev \--no-interaction \--optimize-autoloader# =============================================# ステージ2:final_stage(最小限の実行環境)# =============================================# 軽量なAlpine LinuxベースのPHP-FPMイメージを使用FROM php:8.3-fpm-alpine AS final_stage# セキュリティ:実行用の非特権ユーザーを作成RUN adduser -D appuserUSER appuserWORKDIR /var/www/html# ステージ1からvendorディレクトリのみをコピー# --chown で所有権を同時に変更するのがポイントCOPY --from=build_stage --chown=appuser:appuser /app/vendor ./vendor# アプリケーションのソースコードをコピーCOPY --chown=appuser:appuser . .# PHP-FPMを起動EXPOSE 9000CMD ["php-fpm"]
実行手順
- プロジェクトルートに配置: 上記の
Dockerfileをプロジェクトのルートディレクトリに配置します。 docker buildを実行: 通常通りdocker buildコマンドを実行するだけです。Dockerエンジンが自動的にマルチステージビルドを処理します。
docker build -t my-php-app:prod .
PHPでのポイント
composer_stageの利用: Composerをインストールする手間を省くため、公式のcomposerイメージをビルダーとして使うのが最も効率的です。--no-dev: 開発時のみ必要なパッケージ(テストフレームワークなど)は最終イメージに含めないようにします。USER nonroot: セキュリティのため、最終ステージでは必ずroot権限を放棄し、非特権ユーザーでアプリケーションを実行するように設定しましょう。(これにより、低ポート番号の使用には制約が生じますが、セキュリティが大幅に向上します)COPY --fromの活用: この命令が全てです。Composerの巨大なキャッシュやビルドツール群を最終イメージから排除し、必要なvendorディレクトリだけをクリーンにコピーします。
マルチステージビルドは、軽量で安全なPHPコンテナイメージを作成するための必須技術です。ぜひあなたのプロジェクトに導入してください。
