AWS ECS (Fargate) で Laravel を高速デプロイ!Docker 構成と IaC 運用の最適解

目次

「ECS と EC2 どっちを使えばいい?」「Fargate のタスク定義、何をどう設定すればいいかわからない」——Laravel プロジェクトを初めて AWS に載せようとすると、選択肢の多さに圧倒されがちです。本記事では、Laravel + React プロジェクトを AWS ECS (Fargate) へデプロイするための、実務に即したインフラ設計と Docker 構成を体系的に解説します。CloudFormation による IaC 管理から Dockerfile の最適化、本番運用を見据えたセキュリティ設計まで、一通りの流れを把握できる構成になっています。

AWS ECS (Fargate) を採用する技術的背景

ECS のデプロイ方式には EC2 起動タイプFargate の2種類があります。EC2 の場合はインスタンスの AMI 管理やパッチ適用、スケーリングのための Auto Scaling Group 設定が必要になる一方、Fargate はコンテナの実行基盤をすべて AWS が管理するため、サーバーの存在を意識せずにアプリケーションの開発に集中できます。常時稼働が必要なアプリケーションで中程度の負荷が予想される構成であれば、運用負荷とコストのバランスが取れた現実的な選択肢です。

インフラの管理には CloudFormation による IaC (Infrastructure as Code) を採用します。ネストされたスタック構造(main.yml から 00-vpc.yml40-ecs.yml を呼び出す形式)でリソースを分割管理することで、スタック単位での変更・差し替えが容易になり、チームメンバーが誰でも同じ環境を再現できる「構成の透明性」を確保できます。

インフラ構成と主要リソース

ALB(Application Load Balancer) を入り口とし、ECS Fargate 上で Laravel コンテナを稼働させる構成です。各リソースの設計意図とあわせて整理します。

  • VPC / ネットワーク:CIDR 10.0.0.0/16、2つの Public サブネットに配置。複数 AZ への分散配置により可用性を確保します。
  • Security Groups:HTTP(80) を許可する SGWeb、およびそこからのアクセスのみを許可する SGMysql。最小権限の原則に基づき、DB への直接アクセスを制限しています。
  • ECS Fargate:タスク定義は CPU 256 / Memory 512 を基準に設定。負荷に応じて DesiredCount を変更することでスケールアウトが可能です。AssignPublicIp: ENABLED は ECR などの AWS エンドポイントへのアクセスのために必要な設定です(プライベートサブネット構成にする場合は NAT Gateway または VPC Endpoint が必要)。
  • RDS(MySQL 8.0)db.t3.micro、ストレージ 20GB。本番運用ではマルチ AZ 構成への変更を検討してください。
  • S3(ImageBucket):静的ファイル公開用。バケットポリシーで公開読み取りを許可しています。画像アップロードは Laravel から Minio(ローカル)または S3(本番)へ切り替える設計です。
  • CloudWatch Logs/ecs/ ロググループにて 7 日間のリテンション設定。障害調査のために保持期間はチームの運用フローに合わせて調整してください。

作成した CloudFormation テンプレート例はこちら

エンジニア

マルチステージビルドを採用することで、Node.js や Composer の実行環境を最終イメージに含めず、軽量でセキュアなコンテナを実現しています。イメージサイズの削減は ECR へのプッシュ時間やタスク起動速度にも直結するので、本番環境では必須の最適化です。

デザイナー

インフラが安定していると、デザインした UI/UX がユーザーにストレスなく届きますね。オートスケーリングでトラフィックの波を吸収してくれるので、キャンペーン時のアクセス増加にも安心して対応できます。

Dockerfile の設計:マルチステージビルドの構成と意図

ECS 向けに最適化した Dockerfile(docker/aws/Dockerfile)の構成例です。3つのステージに分けることで、最終イメージにはランタイムに必要なファイルだけが含まれる状態を実現しています。

# --- Stage 1: Node.js(フロントエンドビルド)---
# npm ci で依存関係をロックファイルに基づいて厳密にインストール
FROM node:18 AS node-build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --legacy-peer-deps
COPY resources/js ./resources/js
COPY resources/css ./resources/css
RUN npm run build --if-present

# --- Stage 2: Composer(PHP 依存関係のインストール)---
# --no-dev で開発用パッケージを除外し、本番向けに最適化
FROM composer:2 AS composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --prefer-dist --no-scripts --no-interaction --optimize-autoloader

# --- Stage 3: ランタイム(Apache + PHP)---
FROM php:8.1-apache
RUN apt-get update && apt-get install -y libzip-dev unzip git zip \
    && docker-php-ext-install pdo_mysql zip \
    && a2enmod rewrite

WORKDIR /var/www/html

# 前ステージのアーティファクトだけをコピー(ビルドツールは含まれない)
COPY --from=composer /app /var/www/html
COPY --from=node-build /app/public/build /var/www/html/public/build

RUN chown -R www-data:www-data /var/www/html && chmod -R 755 /var/www/html/storage

EXPOSE 80
CMD ["apache2-foreground"]

ビルドコンテキストはリポジトリルートを想定しています。.dockerignorenode_modulesvendor.git などを除外しておくと、ビルド時の転送量を抑えてキャッシュ効率を高められます。

デプロイの手順と Makefile の活用

複雑な AWS CLI コマンドは Makefile にラップしておくことで、オペレーションミスを防ぎ、チーム全員が同じ手順でデプロイできる状態を維持できます。

  1. ECR ログイン & イメージプッシュ

    make aws-build   # イメージのビルド & ECR へのプッシュ
    make aws-deploy  # CloudFormation を使った AWS へのデプロイ実行
    
  2. インフラ構築・更新
    CloudFormation でスタックを作成します。ImageTag パラメータでデプロイするイメージのタグを指定するため、ロールバック時も特定バージョンへの切り戻しが容易です。
  3. マイグレーションの実行(ECS Exec)
    EnableExecuteCommand: true を設定することで、踏み台サーバーなしに起動中のコンテナ内でコマンドを直接実行できます。

    aws ecs execute-command --cluster <ClusterName> \
      --task <TaskID> --container app --interactive \
      --command "php artisan migrate --force"
    

イメージのビルド & ECR へのプッシュ

echo "🔐 Logging in to ECR..."
$AWS_CLI_CMD aws ecr get-login-password --region "$AWS_DEFAULT_REGION" \
  | docker login --username AWS --password-stdin "$ECR_DOMAIN"

echo "🏗️ Building Docker image..."
# --platform linux/amd64 は Apple Silicon (M1/M2) 環境でビルドする際に必須
docker build --platform linux/amd64 -t "$APP_NAME" \
  -f "$DOCKER_HOME/app/Dockerfile.ecs" "$BASE_DIR"

echo "🏷️ Tagging image..."
docker tag "${APP_NAME}:latest" "$IMAGE_URI"

echo "🚀 Pushing image to ECR..."
docker push "$IMAGE_URI"

CloudFormation を使った AWS へのデプロイ実行

echo "Starting CloudFormation deployment for stack: ${APP_NAME}..."

# create-stack は初回のみ。2回目以降は update-stack または
# change-set を使うことで差分のみ安全に適用できる
$AWS_CLI_CMD aws cloudformation create-stack \
    --stack-name "${APP_NAME}-stack" \
    --template-body "file://docker/aws/template/main.yml" \
    --parameters \
        ParameterKey=ProjectName,ParameterValue="$APP_NAME" \
        ParameterKey=Environment,ParameterValue=dev \
        ParameterKey=TemplateURL,ParameterValue="https://${APP_NAME}-cfm-template.s3.ap-northeast-1.amazonaws.com/" \
        ParameterKey=ImageTag,ParameterValue=latest \
    --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
    --disable-rollback \
    --region ap-northeast-1

echo "Deployment finished. AWS Console でスタックのステータスを確認してください。"

運用上の注意点とベストプラクティス

構築できた後に見落としがちな、本番運用を見据えた重要なポイントを整理します。

  • シークレット管理:現在のテンプレートでは DB 認証情報などが CloudFormation パラメータの平文で渡されています。本番運用では AWS Secrets Manager または SSM Parameter Store(SecureString) に移行し、タスク定義の secrets フィールドから参照する構成を強く推奨します。コードリポジトリに機密情報が混入するリスクを根絶できます。
  • ネットワーク設計:今回の構成では RDS をパブリックサブネットに配置していますが、運用要件に応じてプライベートサブネットへの移行を検討してください。その際は ECS タスクから RDS へのアクセス経路として NAT Gateway、または RDS Proxy の導入も併せて検討します。
  • デプロイ戦略:CloudFormation の create-stack は初回のみ有効です。2回目以降の更新には update-stack または Change Set(変更内容を事前に確認してから適用する仕組み)の活用を推奨します。特に本番環境では Change Set でレビューしてから実行するフローを標準化することで、意図しないリソース削除を防げます。
  • クリーンアップ:CloudFormation スタックを削除すれば関連リソースを一括削除できますが、S3 バケット内のオブジェクトや ECR に蓄積されたイメージは別途削除が必要です。特に ECR はイメージが増え続けるとストレージコストが発生するため、ライフサイクルポリシーで古いイメージを自動削除する設定を入れておくことを推奨します。

まとめ

Laravel + React を ECS Fargate に乗せる構成は、適切に設計すれば運用負荷を最小化しながらスケーラブルな本番環境を維持できます。本記事のポイントを改めて整理します。

  • IaC(CloudFormation)の活用:ネストスタックで関心を分離し、環境構築の再現性とレビュー可能性を確保する。
  • Docker イメージの最適化:マルチステージビルドでビルドツールを最終イメージから除外し、軽量化・セキュア化・デプロイ高速化を同時に実現する。
  • ECS Exec による運用:踏み台サーバーを排除し、コンテナへの直接アクセスで安全かつ手軽にマイグレーションやデバッグを実行できる。
  • 本番に向けたセキュリティ強化:Secrets Manager によるシークレット管理と、プライベートサブネット構成への移行を段階的に進める。

まずはこの構成をベースに動く環境を作り、その上でセキュリティやネットワーク設計を本番仕様へと段階的に引き上げていくアプローチが、実務では最もスムーズに進みやすいはずです。

サンプルアプリケーション

本記事で解説した ECS Fargate へのデプロイ構成を実際に確認・試せるサンプルアプリケーションを公開しています。

🌙 laravel-react-boilerplate

Laravel 12 と React 19 を組み合わせた学習用の EC サイトボイラープレートです。本記事で紹介した CloudFormation テンプレートや Dockerfile、Makefile によるデプロイスクリプトがすべてリポジトリに含まれており、make aws-build & make aws-deploy の2コマンドで ECS へのデプロイを体験できます。

  • インフラ:CloudFormation(ネストスタック)/ ECS Fargate / RDS MySQL 8 / S3 / ALB
  • フロントエンド:React 19 / TypeScript / Tailwind CSS / Vite
  • バックエンド:Laravel 12 / PHP 8.2 / Stripe 決済 / ソーシャルログイン(Google)
  • ローカル開発:Docker Compose / Minio(S3互換)/ Mailpit / Adminer / Storybook

デプロイ構成の参考実装として、また Laravel + React のフルスタック構成を手元で動かしながら学ぶ出発点として活用してみてください。

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。