Laravel を ECS on Fargateにコマンドのみでデプロイ(cloudformation)
この構成を目指す
最新の構成
今後の実装計画
1.Breezeのインストール => RDSの動作確認のため
2. CI / CD設定
2.5. インフラ構成見直し
3. ドメイン登録
4. リファクタ => srcとインフラのリポジトリを分ける => 後回しにする
5. AWS Certificate Manager設定
6. S3 => S3の動作を確認できる機能も実装する
7. localからコンテナとDBにアクセスしたいから踏み台サーバー立てて接続する
8. リファクタ
------- ↓ 暇だったらやる(ここまで実装できたら再度優先順位考える) --------
9. 検証環境作成
10. ElastiCache
11. CloudFront
12. WAF
13. Lambda
14. Queue
15. EventBridge
etc....
現状cloudformationで作成されるリソース
stacks
- vpc
- VPC:10.0.0.0/16
- PublicSubnet1:10.0.0.0/24
- PublicSubnet2:10.0.1.0/24
- RouteTable1
- RouteTable2
- SecurityGroup
- cloudwatch
- LogGroup
- LogStream:Laravel
- LogStream:Nginx
- iam-role
- ECSTaskRole
- ecs
- ECSCluster
- TaskDefinition
- ECSBatchTaskDefinition(batch用タスク定義)
Batchを実行することには成功している
このリポジトリが参考になりそう
readonlyrootfilesystemをtrueにしていたため、nginxで失敗していた
2023/09/05 14:48:47 [emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (30: Read-only file system)
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (30: Read-only file system)
readonlyrootfilesystemをfalseにするとデプロイできた
手順通り実行するとデプロイできる
cloudformationで作成するリソース一覧
- vpc
- VPC:10.0.0.0/16
- PublicSubnet1:10.0.0.0/24
- PublicSubnet2:10.0.1.0/24
- RouteTable1
- RouteTable2
- SecurityGroup
- InternetGateway
- cloudwatch
- LogGroup
- iam-role
- ECSTaskRole
- ecs
- ECSCluster
- ECSService
- TaskDefinition
- ECSBatchTaskDefinition(batch用タスク定義)
- コンテナ:Laravel
- ECSWebTaskDefinition(デプロイ用タスク定義)
- コンテナ:Laravel、Nginx
- ECSBatchTaskDefinition(batch用タスク定義)
次は、ALBとRDSを配置する
あと、PrivateSubnetでコンテナを運用する
作成するリソース
- PrivateSubnet1
- PrivateSubnet2
- RDS
- ALB
ALB配置できた!
現状のインフラ構成
RDSとコンテナをPrivateSubnetに配置する
目的別 クラウド構成
プライベートサブネットにECSを配置した
必要だったリソース
・Private Subnet
・NatGateWay
・EIP
localでmysqlに接続できるように設定しました。
Dokcerfile
FROM php:8.2-fpm
COPY ./src /application
WORKDIR /application
COPY --from=composer /usr/local/bin/composer /usr/local/bin/composer
RUN apt-get update && apt-get install -y \
git \
zip \
unzip \
+ libicu-dev
+ RUN docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd
+ RUN docker-php-ext-configure intl
+ RUN docker-php-ext-install pdo_mysql
RUN composer install
RUN php artisan cache:clear \
&& php artisan config:clear \
&& php artisan route:clear \
&& php artisan view:clear
RUN chown -R www-data:www-data storage
docker-compose.yml
version: '3.5'
services:
nginx:
image: ${REGISTRY_URL}/${PJPrefix}/nginx:latest
platform: linux/x86_64
container_name: ${PJPrefix}-nginx
volumes:
- ./docker/nginx/dev/conf.d/default.conf:/etc/nginx/conf.d/default.conf
ports:
- 8080:80
expose:
- 8080
depends_on:
- laravel
networks:
+ - laravel
laravel:
image: ${REGISTRY_URL}/${PJPrefix}/laravel:latest
platform: linux/x86_64
container_name: ${PJPrefix}-laravel
+ depends_on:
+ - mysql
+ networks:
+ - laravel
volumes:
- ./src:/application
env_file:
- ./src/.env
+ mysql:
+ image: mysql:8.0
+ platform: linux/x86_64
+ container_name: ${PJPrefix}-mysql
+ environment:
+ MYSQL_ROOT_PASSWORD: secret
+ MYSQL_DATABASE: laravel
+ ports:
+ - "3306:3306"
+ volumes:
+ - ./storage/mysql-data:/var/lib/mysql:delegated
+ networks:
+ - laravel
+ networks:
+ laravel:
+ name: laravel
Amazon RDS (Aurora Mysql)の配置完了🎉
赤で囲っている部分の設定は完了した
Breezeのインストールと設定完了
GitHub Actionsの使い方
参考:https://www.youtube.com/watch?v=sx-aIgP2S00
CI / CDで実行したい処理
- LaravelとnginxのECR更新
- build
- laravelとnginxにsrcのリポジトリをクローンする
- composer install
- npm install
- npm run build
- push
- unitテスト実行
- 最新のECRを元にunitテストを実行する
- ECSサービスの更新
- 最新のECRをコンテナに反映する
ポイント
- baseとbuildようでDockerfileを分けた方が良さそう
- baseはbuildの元となるもの
- buildはbaseを元にbuildするもの
build => deploy用
base => 環境構築用
Unitテストで「CSRF token mismatch.」となりテストが通らない問題が発生した
解決策:テストの際はCSRFのミドルウェアを無視するようにした
PRでLaravelのユニットテストを実行するようにした
メモ
act
RDS起動に時間がかかりすぎる
アクセスできない時に確認すること
# nginxのステータスを確認
service nginx status
# ログ確認
nginx -t
nginxとphp-fpmの関係性
nginxとphp-fpmののコンテナを統一する理由
- https://qiita.com/dynamitecoolguy/items/73895292d4c59cb91394
- CDするとき分けていると両方ともにpushする必要があるから面倒
- マルチプロセス対応するために
supervisor
を使った
CI / CDの設定完了!!🎉
Session Manager Install
ecs-cliを使う場合は、Session Manager プラグインのインストールする必要がある
コマンド実行可能か確認コマンド
aws ecs describe-services --cluster laravel-template-cluster --services laravel-template-service | grep enableExecuteCommand
Amazon ECS Exec Checker
brew install jq
bash <( curl -Ls https://raw.githubusercontent.com/aws-containers/amazon-ecs-exec-checker/main/check-ecs-exec.sh ) <YOUR_ECS_CLUSTER_NAME> <YOUR_ECS_TASK_ID>
bash <( curl -Ls https://raw.githubusercontent.com/aws-containers/amazon-ecs-exec-checker/main/check-ecs-exec.sh ) cluster task-arn
- タスクロールにSessionManagerFullAccessを追加する必要があったので、Roleを変更した
aws ecs execute-command \
--cluster cluster \
--task task-arn \
--container nginx \
--interactive \
--command 'php artisan migrate --force'
ECSでマイグレーションを実行しようとしたら以下のエラーが出た
SQLSTATE[HY000] [2002] Connection timed out
環境変数の設定を確認したが問題なく設定されていたので、インフラの設定を確認したらセキュリティーグループに問題があった
以下のようにRDSのセキュリティーグループにECSのセキュリティーグループを指定する必要があった
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${PJPrefix}-DBSecurityGroup"
GroupDescription: !Sub "${PJPrefix}-DBSecurityGroup-Description"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref SG // ECSのセキュリティーグループ
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-DBSecurityGroup"
Privateサブネットに配置しているECSからRDSに接続する場合↑のように設定が必要で、publicに配置しているECSからPrivateのRDSに接続する場合は以下で問題ない。
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${PJPrefix}-DBSecurityGroup"
GroupDescription: !Sub "${PJPrefix}-DBSecurityGroup-Description"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 10.0.0.0/16 // <- 同じVPCから接続できるように
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-DBSecurityGroup"
コスト削減するためにNat GatewayとRDSを見直し、以下の部分を変更した構成を作成しました。(cloudformation-v2)
- Public Subnetには、ECSを配置してNat Gatewayを使わないようにした
- RDSのインスタンスをPrimaryのみにした