🎃

Laravel Sail + ECS + ECRでデプロイフロー構築

2023/08/19に公開4

Background

Objective

  • ローカルでLaravel Sailアプリ作成
  • GitHubでリポジトリ管理
  • ECR, ECSを用いたデプロイ

Environment

  • PHP 8.2.8
  • Laravel 10.18
  • Composer 2.5.8

Deploy

Create Laravel Sail App

  1. 開発ディレクトリで以下コマンド実行
laraevl new deploy-back
cd deploy-back
composer require laravel/sail --dev
php artisan sail:install
composer install
./vendor/bin/sail up
  1. localhostにアクセスして画面が表示されればOK

Push to GitHub

  1. GitHubにリポジトリ作成(以下リポジトリ名を deploy-back とする)
  2. 先ほど作成したlaravelアプリのディレクトリで以下コマンド実行
git init
git add .
git commit -m 'first commit'
git remote add origin {作成したリポジトリURL}
git push origin master
  1. GitHubを確認してプッシュできていればOK

Create AWS VPC

デプロイ環境を構築するためにAWSでVPCを作成

  1. VPC > Create VPCからVPC~IGWまで一括で作成

Create AWS Security Group

テスト用のセキュリティグループを作成

  1. VPC > Security Group > Create security groupから作成
  2. 先程作成したVPCを選択して、Inbound rules, Outbound rulesに適切な設定をする

Create AWS ECR Repository

  1. AWS > Elastic Container Registry > Private > Create repositoryでリポジトリを作成
  2. Private, Repository name = deploytestで作成

Create Dockerfile for ECR

laravelディレクトリ内にECRデプロイ用のDockerfileを作成

  1. php artisan sail:publishでdockerディレクトリ配下をリポジトリ管理対象にする
  2. /docker/8.2配下にapache設定用の000-default.confファイル作成
// 000-default.conf
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html/public

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Directory /var/www/html/public>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
  1. /var/www/html直下に以下の内容でDockerfileを作成
// Dockerfile
FROM php:8.2-apache
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]

ENV COMPOSER_ALLOW_SUPERUSER=1 \
  COMPOSER_HOME=/composer

COPY --from=composer:2.2 /usr/bin/composer /usr/bin/composer

RUN apt-get update && \
  apt-get -y install git unzip libzip-dev libicu-dev libonig-dev libpq-dev libfreetype6-dev libjpeg62-turbo-dev libpng-dev  && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/* && \
  docker-php-ext-install intl pdo_mysql zip bcmath

RUN pecl install xdebug && \
    docker-php-ext-enable xdebug

RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ && \
    docker-php-ext-install -j$(nproc) gd

RUN mv /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled
RUN /bin/sh -c a2enmod rewrite
WORKDIR /var/www/app
COPY . /var/www/app
COPY ./docker/8.2/000-default.conf /etc/apache2/sites-available/000-default.conf
COPY ./docker/8.2/php.ini /usr/local/etc/php/php.ini

RUN composer require predis/predis

RUN composer install \
  && chmod -R 777 storage bootstrap/cache public/
RUN php artisan config:cache
RUN php artisan route:cache
RUN php artisan view:cache
RUN curl -sL https://deb.nodesource.com/setup_lts.x | bash -
RUN apt-get install -y nodejs
RUN npm install npm@latest
RUN npm run build

Push to ECR

  1. ECRでリポジトリ作成後に詳細画面に行けるので、右上にあるView push commandsからプッシュ用のコマンドを確認
  2. 書かれているコマンドをlaravelディレクトリで実行
  3. 成功してリポジトリのImagesにlatestで表示されればOK

Create ECS

Elastic Container Serviceから各設定をする

Task definition

Elastic Container Service > Task definitions > Create new task definitionから作成
ECSで起動するためのタスクを作成する

Task definition famimly

Container


他の設定はデフォルトのまま作成

Cluster

Elastic Container Service > Clusters > Create clusterからクラスターを作成

  1. クラスター名、作成したVPCとSubnetsを設定して作成
  2. 作成すると以下のような詳細画面に遷移できる

Service

クラスター詳細画面からService > Createでサービスを作成

Environment

Launch type, FARGATEを選択

Deployment configuration

Service, 作成したタスク定義、作成するサービス名を設定

Networking

作成したVPC, Subnets, Security groupを設定、Public IPはONにする

上記設定でサービスを作成するとサービスが立ち上がる

サービス詳細からタスクのコンテナを確認するとPublic IPが確認できる

Public IPにアクセスしてLaravelアプリが立ち上がっていればOK

Deploy Flow

Create buildspec.yml for Code Build

laravelディレクトリでCode Build用にbuildspec.ymlファイルを作成する
/var/www/html直下にbuildspec.ymlを以下の内容で作成

version: 0.2
# Codebuild用設定ファイル
phases:
  pre_build:
    commands:
      - aws --version
      - echo Logging in to Amazon ECR....
      - aws ecr get-login-password --region {region} | docker login --username AWS --password-stdin {Account ID}.dkr.ecr.ap-northeast-1.amazonaws.com
  build:
    commands:
      - echo Build started on `date`
      - docker build -f ./Dockerfile -t {ECR name}:latest .
      - docker tag {ECR name}:latest {Account ID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECR name}:latest
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker image ls -a
      - docker push {Account ID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECR name}:latest
      - printf '[{"name":"%s","imageUri":"%s"}]' {ECR name} {Account ID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECR name}:latest > imagedefinitions.json
artifacts:
  files:
    - imagedefinitions.json

{ }の中身については各自の環境に合わせて設定

  • {region}: ap-northeast-1など
  • {Account ID}: AWSのアカウントID
  • {ECR name}: 作成したECRのリポジトリ名(deploytest)

Create Code Build

CodeBulid > Build projects > Create build projectから作成

Source

デプロイしたGitHubのlaravelアプリのリポジトリを選択

Primary source webhook events

Webhookの発火条件を指定(PUSH:GitHubにプッシュされた時に発火)

Environment

Privilegedにチェック(これがないとbuildspec.ymlでimageを作成できない)

Buildspec

作成したbuildspec.ymlの名前を入れる

上記設定でBuild project作成

CodePipeline

  1. Codepipeline > Create new pipelineから作成

Choose pipeline setting

パイプライン名とロールを設定

Source

GitHubを選択してLaravelアプリのリポジトリ、ブランチを設定

Add build stage

Build providerにCodeBuildを設定し、作成したBuild projectを設定

Add deploy stage

Deploy providerにECSを設定し、作成したクラスター、サービスを設定
Image definition fileにはbuldspec.ymlのartifacts > filesに記載したファイル名を入れる

上記設定でCodePipeline作成

Check

試しにGitHubにプッシュして動作確認し、問題なければデプロイ成功

Discussion

yoshidakoutarouyoshidakoutarou

記事拝見させていただきました。
そこで気になったのですが、ディレクトリ構造をどの様にしていますか?
また、3項目目の

/var/www/html直下に以下の内容でDockerfileを作成

こちらはどこに作成しているのでしょうか?
プロジェクトディレクトリ直下に/var/www/htmlを作成している認識であっていますか?

HutonmanHutonman

ディレクトリ構成は以下のような感じです。

プロジェクトディレクトリ/ (laravelコンテナのvar/www/html)
 ├ app/
 ├ bootstrap/
 ├ confiig/
   ...
 ├ docker/ (php artisan sail:publishコマンドで作成)
 │ └ 8.2/
 │   └ 000-default.conf
 │   └ Dockerfile
...   └ php.ini
 └ .env
 └ buildspec-development.yml
 └ docker-compose.yml
 └ Dockerfile

/var/www/htmlはプロジェクトディレクトリのことで、Dockerfileはプロジェクトディレクトリ直下に作成します。

yoshidakoutarouyoshidakoutarou

お返事ありがとうございます。
000-default.confを作成せずに、接続テストを行なってみたのですが、ALBでヘルスチェックを通過しているのにも関わらず、503エラーが出たのですが、そういった症状が発生したことはありますか?
apache設定をしていないためコネクションタイムアウトになったと言うことでしょうか?

HutonmanHutonman

自分がやっていく中では発生していなかったと思います。
詳細がわからないのでなんとも言えませんが、一度000-default.confを作成して確認するか、エラーログなどを確認してみるといいかと思います。