LoginSignup
72
63

More than 1 year has passed since last update.

Laravel 9 を ECS on Fargateで構築

Last updated at Posted at 2022-04-03

はじめに

Laravel9をFargateで構築する方法を記載します。
下記のソースをそのまま使いますので、クローンしてください。

環境

  • fargate
  • PHP : 8.1
  • Laravel : 9.2.0
  • Nginx : 1.20

完成構築図

スクリーンショット 2022-03-30 23.50.18.png

事前構築

スクリーンショット 2022-03-30 23.59.42.png

  • VPC,インターネットゲートウェイ,サブネット,RDSまで作成済み
    • RDSを作成する際、追加設定データベース名:「laravel_ecs」を作成してください。マスターユーザー名とパスワードも使いますので、メモしておきましょう。

ソースのディレクトリ構造

ソースをクローン後に、ディレクトリ構造を確認します。

laravel-ecs % tree
.
├── docker
│   ├── nginx
│   │   ├── Dockerfile
│   │   ├── default.conf
│   │   └── nginx.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
└── src
    ├── README.md
    ├── app
    ├── .env.production
    ├── artisan
    ├── bootstrap
    ├── composer.json
    ├── composer.lock
    ├── config
    ├── database
    ├── lang
    ├── package.json
    ├── phpunit.xml
    ├── public
    │   └── index.php
    ├── resources
    ├── routes
    ├── storage
    ├── tests
    └── webpack.mix.js
.env.production
APP_KEY=すでに作成済みのものか上記のAPP_KEYを入れる
DB_CONNECTION=mysql
DB_HOST=RDSのエンドポイントを記述
DB_PORT=3306
DB_DATABASE=laravel_ecs
DB_USERNAME=RDS作成の際に設定したマスターユーザー名
DB_PASSWORD=RDS作成の際に設定したマスターパスワード

ALBを作成

ALBを以下の項目を適切に選択し、作成します。
他の項目は、全てデフォルトでよいです。
 ・名前:何でも
 ・VPC:作成したVPC
 ・サブネット:作成したパブリックサブネット
 ・セキュリティーグループ(インバウンド:0.0.0.0に対して、HTTPとHTTPSを許可します)

・リスナー:HTTP:80

ターゲットグループ作成

  • ターゲットタイプ:インスタンス
  • ターゲットグループ名:何でも
  • Choose a target type:IP addresses
  • HTTP:80
  • Health check path:HTTP/
    スクリーンショット 2022-04-10 10.37.44.png
    スクリーンショット 2022-04-02 10.40.16.png

Include as pending belowは、押さずに、ターゲットグループを作成

ロードパランサーの作成画面に戻り、他はデフォルトで作成。

ALBのリスナーの確認

ターゲットグループがfargateのみになっているか確認します
スクリーンショット 2022-04-02 18.19.18.png

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

elbのsgに対して、httpを許可します。
HTTP:ソースalbのセキュリティーグループを選択
スクリーンショット 2022-04-10 10.44.10.png

RDSのセキュリティーグループを修正

fargateのsgに対して、MYSQL/Auroraを許可するように修正します。
スクリーンショット 2022-04-02 18.16.57.png

Route53を作成

Route53を作成します。
 ・ドメイン名:xxxx.com
 ・タイプ:パブリックホストゾーン

次に、独自ドメインのネームサーバー情報を変更します。
以下の4つのネームサーバー情報を貼り付けます。

ネームサーバー情報の変更方法:お名前ドットコム

ドメイン→ドメイン機能一覧→ネームサーバー設定画面に移動し、その他のタブから入力できます。

Route53レコードの設定

Route53を利用して独自ドメインとALBのDNS名を紐づけます。
ホストゾーンxxxx.comのレコードを作成します
 ・レコード名:<空白>
 ・レコードタイプ:A
 ・エイリアス:選択します
 ・トラフィックのルーティング先:ALB,東京リージョン、先程作成したALBを選択
 ・ルーティングポリシー:シンプルルーティング

スクリーンショット 2022-04-02 10.17.29.png

IAMユーザーの作成

ECRにDockerイメージをプッシュする際、cliを利用するため、事前にIAMユーザーを作成し、アクセスキーを発行しておきましょう。
IAMポリシーは、EC2InstanceProfileForImageBuilderECRContainerBuildsをアタッチします。

aws configure --profileコマンドを使用し、アクセスキーとシークレットキーを設定します。

$ aws configure --profile fargate-laravel
AWS Access Key ID [None]: ****************DMH2
AWS Secret Access Key [None]: ****************bHBU
Default region name [None]: ap-northeast-1
Default output format [None]:

// aws cli プロフィール変更
$ export AWS_DEFAULT_PROFILE=fargate-laravel

これでローカルでのcliのセットは完了です。

ECRを作成

AWSのECSのコンソール画面からECRのリポジトリをクリックします
nginxappリポジトリの2つを作成します。
 ・可視性設定:プライベート
 ・リポジトリ名:nginx
 ・その他はデフォルト設定のまま

 ・可視性設定:プライベート
 ・リポジトリ名:php
 ・その他はデフォルト設定のまま

プッシュコマンドの表示をクリックすると以下の画面が出てきます。
スクリーンショット 2022-04-02 11.41.07.png

この4つのコマンドの流れでECRにpushしていきます。

ソースをクローンした後、ソースのルートディレクトリに移動し、ecrのログインをします。

$ cd laravel-ecs

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded

ログインできました。

ログインに失敗した場合、IAMユーザーのアクセスキーIDとシークレットアクセスキーが以下の情報と一致しているか確認してください。
一致していない場合、IAMユーザーから新たにアクセスキーを発行し、~/.aws/credentials~/.aws/configファイルを修正してください。

// profileの確認
$ cat ~/.aws/credentials
$ cat ~/.aws/config

// profileの確認
$ aws configure --profile fargate-laravel
AWS Access Key ID [None]: ****************DMH2
AWS Secret Access Key [None]: ****************bHBU
Default region name [None]: ap-northeast-1
Default output format [None]:

// aws cli プロフィール変更
$ export AWS_DEFAULT_PROFILE=fargate-laravel

ログイン後、nginxをビルドし、タグ付け後、ECRにpushします。

今回は、タグは、latestではなくprodにします。
実際にサービスを構築する際、タグをproddevstgと、環境別にイメージタグを作成するため、prodにしました。

laravel-ecs $ docker build -t nginx:prod -f ./docker/nginx/Dockerfile .

$ docker tag nginx:prod [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/nginx:prod

$ docker push [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/nginx:prod

問題なくpushできれば、ECRのリポジトリにイメージが作成されます。
スクリーンショット 2022-04-03 9.22.41.png

同様にphpでもビルドし、タグ付け後、ECRにpushします。

laravel-ecs $ docker build -t php:prod -f ./docker/php/Dockerfile .

$ docker tag php:prod [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/php:prod

$ docker push [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/php:prod

スクリーンショット 2022-04-03 9.23.03.png

phpとnignxのイメージをpushできました。

クラスターを作成

ECSのコンソール画面からクラスターの作成をクリックします。

ネットワーキングのみを選択し、次のステップ

クラスター名を記入し、作成します。

スクリーンショット 2022-04-02 12.31.26.png
container insightsは有効にします。

タスク定義を作成

ECSのコンソール画面のタスク定義タブから新しいタスク定義の作成をクリックします
 ・起動タイプ:Fargate
次へ
 ・タスク定義名:laravel-prod
 ・タスクロール:なし
 ・ネットワークモード:awsvpc
 ・タスク実行ロール:ecsTaskExecutionRole(デフォルト)

スクリーンショット 2022-04-02 17.31.20.png

コンテナの追加php

  • コンテナ名:php

  • イメージ:リポジトリのイメージのURI

    • ECRのphpをクリックすると、イメージのURIがありますのでコピペしましょう。
    • スクリーンショット 2022-04-02 17.34.27.png
  • 環境

    • エントリポイント:sh,-c

    • コマンド:php artisan config:cache && php artisan view:cache && php artisan route:cache && php artisan migrate --force && chown -hR www-data:www-data storage bootstrap/cache && php-fpm && composer install --optimize-autoloader --no-dev

    • 作業ディレクトリ:/var/www/html

    • スクリーンショット 2022-11-12 16.52.34.png

    • 環境変数

      • APP_ENV: production

環境変数APP_ENV:Value:productionを設定すると、env.productionを読み取ってくれます。

コマンドは、以下を参考にしております。

  • 他はすべてデフォルトのままです

更新をクリックするとコンテナが作成されます。

コンテナの追加nginx

  • コンテナ名:nginx
  • イメージ:リポジトリのイメージのURI
    • ECRのnginxをクリックすると、イメージのURIがありますのでコピペしましょう。
  • ポート:80
  • 他はすべてデフォルトのままです

更新をクリックするとコンテナが作成されます。

他はすべてデフォルトのままでタスク定義を作成します。

サービスを作成

クラスターからサービスを作成します。
スクリーンショット 2022-04-02 17.51.40.png

  • サービスの設定

    • 起動タイプ:FARGATE
    • タスク定義 ファミリー:laravel-prod
    • タスク定義 リビジョン:1(latest)
    • プラットフォームのバージョン:1.4.0
    • クラスター:laravel
    • サービス名:laravel-prod
    • タスク数の数:1
      スクリーンショット 2022-04-02 17.53.49.png
  • 次のステップ

    • クラスター VPC:適切なvpc
    • サブネット:パブリックサブネット
    • セキュリティーグループ:既存のセキュリティーグループを選択先程作成したsgを選択します
    • ロードバランシング
      • Application Load Balancer
      • ロードバランサー名:ロードバランサー選択
      • プロダクションリスナーポート:80:HTTP
      • ターゲットグループ名:先程作成したターゲットを選択
      • ターゲットグループのプロトコル:HTTP
      • パスパターン:/
      • 評価順:default
      • ヘルスチェックパス:/
        スクリーンショット 2022-04-10 10.54.00.png

ターゲットグループを新規で作成する場合は、以下の設定になります。

スクリーンショット 2022-04-03 0.09.04.png

elbからfargate(task)に対して、ポート80でアクセスされ、task内のnginxのポート80に繋がります。

elbにacm(証明書)を入れている場合、プロダクションリスナーポートは、HTTPSを選択できるようになります。

次のステップ
 ・autoscalingなし

サービスが作成されました!

http://xxxx.com/にアクセスすると、laravelが表示されました!
スクリーンショット 2022-04-02 23.37.11.png
表示されない場合、以下のエラーの可能性があります。

エラー集

ResourceInitializationError

ResourceInitializationError: 
unable to pull secrets or registry auth: execution resource retrieval failed:
unable to retrieve ecr registry auth: service call has been retried 3 time(s):
RequestError: send request failed caused by: Post https://api.ecr....

スクリーンショット 2022-04-02 18.26.45.png

privateサブネットで起動

fargateをprivateサブネットで起動した場合、以下のエラーが出ます。publicサブネットに変更しましょう。

セキュリティーグループ

sgを確認してください。

  • elbのsgは、httpで全開放(0.0.0.0/0)
  • fargateのsgは、elbからのhttpで許可
  • ACLとセキュリティグループが、サブネットからのポート 443 へのアウトバウンドアクセスを許可

exec /docker-entrypoint.sh: exec format エラー

スクリーンショット 2022-10-20 11.47.04.png

原因は、M1チップのPCでビルドしたため、ビルドするマシンと実行するマシンのCPUアーキテクチャが異なると起動に失敗するようです。

ビルド時、--platform amd64をつけるとうまく起動します。

$ laravel-ecs $ docker build -t nginx:prod -f --platform amd64 ./docker/nginx/Dockerfile .

sh: php: not foundエラー

タスクのログを確認すると、phpのコンテナに以下の記載があります。

sh: php: not found

スクリーンショット 2022-11-07 17.48.51.png

スクリーンショット 2022-11-07 17.49.05.png

これは、phpのコンテナ内にnginxのイメージが入り、nginxのコンテナ内にphpのイメージが入っていることが原因でした。

コンテナがすぐに停止する場合

コンテナがRunningとなってもすぐにコンテナがStopされる場合、以下の確認をしてみてください

ヘルスチェックに失敗

エラーログが下記の場合、nginxの設定ミスによるもので、default.confファイル、もしくは、ヘルスチェックパスを修正します。

2022/04/04 16:49:54 [error] 32#32: *2 directory index of "/var/www/html/" is forbidden, client: xx.x.x.xx, server: , request: "GET / HTTP/1.1", host: "xx.x.x.xxx"

default.conf修正

index index.php;がない可能性があります。ない場合、追加してください

docker/nginx/default.conf
server {
  listen 80;
  root /var/www/html/public;
  error_log /var/log/nginx/error.log;
+  index index.php;

また、ターゲットグループのヘルスチェックパスが/になっていることを確認しましょう。

LaravelのAPP_KEYがない場合

APP_KEYをenvファイルに記載していない場合、コンテナがRunning時に、http://xxxx.com/にアクセスすると、以下のエラー表示がされます。

No application encryption key has been specified.

スクリーンショット 2022-04-02 23.29.53.png

APP_KEYがない、暗号化されていないことが原因です。
とりあえず、envファイルにAPP_KEY=base64:Wya0dp/iTvZJrXW0qM5uSTR2JugldcCMambNZNzR9Kc=を加えて、再度ビルドしてください。

APP_KEY作成方法

オリジナルのAPP_KEYを作成したい場合、fargate内にアクセスし、key作成コマンドを実行する必要があります。

下記の記事通りに行い、fargate内にアクセスします。

aws ecs execute-command \
    --cluster laravel \
    --task <タスクID> \
    --container php \
    --interactive \
    --command "/bin/sh"

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


Starting session with SessionId: ecs-execute-command-0e408d1fb1cba10cf

# pwd
/var/www/html

# php artisan key:generate --show
base64:Wya0dp/iTvZJrXW0qM5uSTR2JugldcCMambNZNzR9Kc=

Fargate EXEC でコンテナに入りAPIキーを作成するためには、コンテナがRuuning時に、Fargate EXECする必要があります。
今回のAPP_KEYがないエラーの場合、コンテナが起動停止を繰り返しますので、とりあえず、先程のAPP_KEYを加えビルドし、エラーを解消しましょう。
コンテナが起動で安定した後、Fargate EXECし、APIキーを作成するようにしましょう。

envファイルAPP_KEY=base64:Wya0dp/iTvZJrXW0qM5uSTR2JugldcCMambNZNzR9Kc=を追加し、再ビルドし、pushします。
phpソース内の修正なので、phpコンテナのみで良いです。念の為、nginxも同様にビルドしてもよいかもしれませんが。

laravel-ecs $ docker build -t php:prod -f ./docker/php/Dockerfile .

$ docker tag php:prod [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/php:prod

$ docker push [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/php:prod

サービス画面に遷移し、強制デプロイにチェックし、更新します。

スクリーンショット 2022-04-03 9.40.31.png
新しいタスク起動後、http://xxxx.com/にアクセスすると、laravelが表示されました!

運用や機能追加するTIP集

  • Fargateで構築したLaravelを運用にする上で、ポイントまとめています。

  • こちらの記事では、Fargate で構築した Laravel の コンテナを 読み取り専用(ReadOnly)にする方法について説明しております。

  • こちらの記事では、Fargate で構築した Laravel で Supervisor を導入する方法について説明しております。

参考

エントリーポイントについて

タスク定義

72
63
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
72
63