Closed23

Laravel を ECS on Fargateにコマンドのみでデプロイ(cloudformation)

ピン留めされたアイテム
YoppyYoppy

今後の実装計画
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....

YoppyYoppy

現状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を実行することには成功している

YoppyYoppy

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にするとデプロイできた

YoppyYoppy

手順通り実行するとデプロイできる
https://github.com/yoppyDev/laravel-fargate-cloudformation/tree/30160ada8ecf30d649f3b7d672781bf3fdbbeab1

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
YoppyYoppy

次は、ALBとRDSを配置する
あと、PrivateSubnetでコンテナを運用する

作成するリソース

  • PrivateSubnet1
  • PrivateSubnet2
  • RDS
  • ALB
YoppyYoppy

localでmysqlに接続できるように設定しました。
https://github.com/yoppyDev/laravel-fargate-cloudformation/tree/8f712e6b054db599fa7f2107d4f7ffe1ad33eee4

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
YoppyYoppy

CI / CDで実行したい処理

  1. LaravelとnginxのECR更新
  • build
    • laravelとnginxにsrcのリポジトリをクローンする
    • composer install
    • npm install
    • npm run build
  • push
  1. unitテスト実行
  • 最新のECRを元にunitテストを実行する
  1. ECSサービスの更新
  • 最新のECRをコンテナに反映する

ポイント

  • baseとbuildようでDockerfileを分けた方が良さそう
  • baseはbuildの元となるもの
  • buildはbaseを元にbuildするもの

build => deploy用
base => 環境構築用

YoppyYoppy

メモ

act
https://github.com/nektos/act

RDS起動に時間がかかりすぎる
https://www.ikura-oisii.com/1349/

アクセスできない時に確認すること

# nginxのステータスを確認
service nginx status

# ログ確認
nginx -t

nginxとphp-fpmの関係性
https://www.datadoghq.com/blog/nginx-502-bad-gateway-errors-php-fpm/

nginxとphp-fpmののコンテナを統一する理由

YoppyYoppy

Session Manager Install
ecs-cliを使う場合は、Session Manager プラグインのインストールする必要がある

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/install-plugin-macos-overview.html

コマンド実行可能か確認コマンド

aws ecs describe-services --cluster laravel-template-cluster --services laravel-template-service | grep enableExecuteCommand

Amazon ECS Exec Checker
https://github.com/aws-containers/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'
YoppyYoppy

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"
このスクラップは3ヶ月前にクローズされました