【コマンドベース】Fargate + ECR + ECS 構成による FastAPI dynamoDB 連携サービスの稼働

## Fargate + ECR + ECS 構成による　FastAPI 阿呆＆馬鹿データベースサービスの稼働
### 通常コンテナ更新時サマリー
|リージョン|クラスター名             |タスク定義ファミリー         |サービス名               |
|--------|-----------------------|--------------------------|-----------------------|
|$REGION |$CONTAINER_NAME-cluster|$SCONTAINER_NAME-definition|$CONTAINER_NAME-service|

* ローカル端末でのコンテナサービステスト
  ```bash
  cd ~/aws/mongodb && source ./Local_Container_Service_Test.sh
  ```
* 既存のAWS ECSのクラスター、タスク定義、サービFVスに対して更新
  ```bash
  cd ~/aws/mongodb && source ./Upadte_Cluster_TaskDef_Service.sh
  ```
* 更新したECSサービスのタスクのパブリックIPを取得しテストを実行 ※数分待ってから実行
  ```bash
  cd ~/aws/mongodb && source ./Get_ECS_Service_task_IP_Address.sh
  ```
* サービスの実行例
  <details><summary>hoge_foo POST サービス</summary>

    ```bash
    cd ~/aws/mongodb && source ./Get_ECS_Service_task_IP_Address.sh
    BAKA_ID=C202310250001 && BAKA_NMAE="阿保田 太郎" && BOKE_ID=B00001 && COMP_NUM=02
    echo $PUBLIC_IP':'$BAKA_ID':'$BAKA_NMAE':'$BOKE_ID':'$COMP_NUM
    curl -X 'GET' 'http://'$PUBLIC_IP
    curl -X 'POST' \
      'http://'$PUBLIC_IP'/hoge_foo/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{
      "foo": {
            "id_foo": "'$BAKA_ID'",
            "name": "'$BAKA_NMAE'"
      },
      "job_description": {
            "bakatare_ID": "'$BOKE_ID'",
            "JD_Number": "'$COMP_NUM'"
      }
    }'
    ```
  </details>

### Dockerファイル
<details><summary>Dockerfile_$CONTAINER_NAME</summary>
  
  ```bash
  FROM --platform=linux/amd64 tiangolo/uvicorn-gunicorn-fastapi:python3.11
  #FROM --platform=linux/amd64 python:3.11.4-slim-buster

  # 作業ディレクトリを設定する
  WORKDIR /app

  # 既存のディレクトリを削除
  RUN rm -rf /app/*

  # 必要なパッケージをインストールする
  RUN apt-get update && apt-get install -y git
  ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" /dev/null
  RUN git clone https://ghp_AAAABbbbbcccDDDDFFFFhhh@github.com/baka-mono/mongodb.git .
  RUN pip install --upgrade pip
  RUN pip3 install -r requirements.txt
  RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt

  # アプリケーションを実行する
  ENV AWS_DEFAULT_REGION=us-east-1
  ENV AWS_ACCESS_KEY_ID=ABCDEFGHIJKLMNOPQ
  ENV AWS_SECRET_ACCESS_KEY=abcd123abcd123abcd123abcd123
  CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
  ```
</details>

### シェルスクリプト
* ローカル端末でのコンテナサービステスト
  <details><summary>./Local_Container_Service_Test.sh</summary>
      
    ```bash
    ## 0. 環境変数を設定
    export AWS_ACOUNT_ID=12345678901
    export REGION=us-east-1
    export AWS_PROFILE=bakaconf
    export CONTAINER_NAME=foo_bakatare
    export KIND=fastapi
    export IMAGE_MAME=$CONTAINER_NAME'-'$KIND

    ## 1. GitHubリモートリモートリポジトリの更新
    git add . && git commit -m "regular update" && git push -u origin main

    ## 2. Dockerコンテナをビルド
    cd ~/aws/mongodb/ && docker ps -a && docker images && ./remove_container.sh $CONTAINER_NAME
    docker build -t $IMAGE_MAME -f Dockerfile_$CONTAINER_NAME .
    docker ps -a && docker images

    ## 3. Dockerコンテナサービスを実行
    docker run -d -p 80:80 --name $IMAGE_MAME $IMAGE_MAME
    sleep 6
    docker ps -a && docker images

    ## 4. Dockerコンテナの稼働状況ログを出力
    docker logs $(docker ps -q --filter "name=$CONTAINER_NAME-fastapi")

    ## 5. ローカル端末でサービスをテスト
    echo "ーーー" && echo "【テスト】＜foote テーブル＞バカのヒートマップ用インデックス"
    curl -X 'POST' \
      'http://localhost/foo/heatmap/baaba/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"id_foo":"C202310250001","name":"阿保田 太郎"}'
    echo "ーーー" && echo "【テスト】＜foote テーブル＞ジジイの「現状の抜作」と「今後の間抜」ヒートマップ用インデックス"
    curl -X 'POST' \
      'http://localhost/foo/heatmap/booo/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"id_foo":"C202310250001","name":"阿保田 間抜け"}'
    echo "ーーー" && echo "【テスト】＜aho_bakatareテーブル＞バカのヒートマップ用インデックス"
    curl -X 'POST' \
      'http://localhost/job_description/heatmap/baaba/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"bakatare_ID":"B00001","JD_Number":"02"}'
    echo "ーーー" && echo "【テスト】＜aho_bakatareテーブル＞ジジイの「現状の抜作」と「今後の間抜け」ヒートマップ用インデックス"
    curl -X 'POST' \
      'http://localhost/job_description/heatmap/booo/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"bakatare_ID":"B00001","JD_Number":"02"}'
    ```
  </details>
* 既存のクラスター、タスク定義、サービスに対して更新
  <details><summary>./Upadte_Cluster_TaskDef_Service.sh</summary>
      
    ```bash
    #---------------------------------------------------
    # 既存のクラスター、タスク定義、サービスに対して更新をかける 
    #---------------------------------------------------
    ## 0. 環境変数を設定
    export AWS_ACOUNT_ID=12345678901
    export REGION=us-east-1
    export AWS_PROFILE=bakaconf
    export CONTAINER_NAME=foo_bakatare
    export KIND=fastapi
    export IMAGE_MAME=$CONTAINER_NAME'-'$KIND

    ## 1. GitHubリモートリモートリポジトリの更新
    git add . && git commit -m "regular update" && git push -u origin main

    ## 2. Dockerコンテナをビルドし、コンテナイメージにタグを付与
    cd ~/aws/mongodb/ && docker ps -a && docker images && ./remove_container.sh $CONTAINER_NAME
    docker build -t $IMAGE_MAME -f Dockerfile_$CONTAINER_NAME .
    TAG_NAMING='docker tag '$IMAGE_MAME':latest '$AWS_ACOUNT_ID'.dkr.ecr.'$REGION'.amazonaws.com/'$IMAGE_MAME':latest'
    eval $TAG_NAMING
    docker ps -a && docker images

    ## 3. 認証トークンを取得し、レジストリに対して Docker クライアントを認証
    echo $AWS_ACOUNT_ID' : '$REGION' : '$AWS_PROFILE' : '$CONTAINER_NAME' : '$KIND' : '$IMAGE_MAME
    aws ecr get-login-password --region $REGION --profile $AWS_PROFILE | docker login --username AWS --password-stdin $AWS_ACOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

    ## 4. DockerイメージをECRにプッシュ
    docker push $AWS_ACOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$IMAGE_MAME

    ## 5. 新しいタスク定義を登録
    aws ecs register-task-definition \
      --family $CONTAINER_NAME-definition \
      --network-mode awsvpc \
      --requires-compatibilities FARGATE \
      --cpu "256" \
      --memory "512" \
      --execution-role-arn arn:aws:iam::$AWS_ACOUNT_ID':role/ecsTaskExecutionRole' \
      --container-definitions '[
        {
          "name": "foo_bakatare-container",
          "image": "'$AWS_ACOUNT_ID'.dkr.ecr.'$REGION'.amazonaws.com/'$IMAGE_MAME':latest",
          "essential": true,
          "portMappings": [
            {
              "containerPort": 80,
              "hostPort": 80
            }
          ]
        }
      ]' \
      --region $REGION

    ## 6. 新しいタスク定義のARNを取得
    NEW_TASK_DEF_ARN=$(aws ecs describe-task-definition --task-definition $CONTAINER_NAME-definition --query 'taskDefinition.taskDefinitionArn' --output text)

    ## 7. 新しいタスク定義を使用して既存のサービスを更新
    aws ecs update-service \
      --cluster $CONTAINER_NAME-cluster \
      --service $CONTAINER_NAME-service \
      --task-definition $NEW_TASK_DEF_ARN \
      --force-new-deployment \
      --region $REGION
    ```
  </details>
* 更新したECSサービスのタスクのパブリックIPを取得しテストを実行
  <details><summary>./Get_ECS_Service_task_IP_Address.sh</summary>

    ```bash
    #---------------------------------------------------
    # 更新したECSサービスのタスクのパブリックIPを取得
    #---------------------------------------------------
    ## 0. 定数を設定
    AWS_ACOUNT_ID=12345678901 && REGION=us-east-1 && AWS_PROFILE=bakaconf && CONTAINER_NAME=foo_bakatare && KIND=fastapi && IMAGE_MAME=$CONTAINER_NAME'-'$KIND

    ## 1. 実行中のタスクのARNを取得:
    TASK_ARN=$(aws ecs list-tasks --cluster $CONTAINER_NAME-cluster --service-name $CONTAINER_NAME-service --desired-status RUNNING --query 'taskArns[0]' --output text)
    echo $TASK_ARN

    ## 2. タスクの詳細を取得:
    ENI_ID=$(aws ecs describe-tasks --cluster $CONTAINER_NAME-cluster --tasks $TASK_ARN --query 'tasks[0].attachments[0].details[?name==`networkInterfaceId`].value' --output text)
    echo $ENI_ID

    ## 3. ENI（Elastic Network Interface）のパブリックIPを取得:
    PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids $ENI_ID --query 'NetworkInterfaces[0].Association.PublicIp' --output text)
    echo $PUBLIC_IP

    ## 4. パブリックIPを使用してサービスをテスト:
    echo "" && echo "【テスト】バカのヒートマップ用インデックス"
    curl -X 'POST' \
      'http://'$PUBLIC_IP'/foo/heatmap/baaba/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"id_foo":"C202310250001","name":"阿保田 間奴け"}'
    echo "" && echo "" && echo "【テスト】ジジイの「現状の抜作」と「今後の間抜け」ヒートマップ用インデックス"
    curl -X 'POST' \
      'http://'$PUBLIC_IP'/foo/heatmap/booo/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"id_foo":"C202310250001","name":"阿保だ 太郎"}'
    echo "" && echo "" && echo "【テスト】＜aho_bakatareテーブル＞バカのヒートマップ用インデックス"
    curl -X 'POST' \
      'http://'$PUBLIC_IP'/aho_bakataren/heatmap/baaba/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"bakatare_ID":"B00001","JD_Number":"02"}'
    echo "" && echo "" && echo "【テスト】＜aho_bakatareテーブル＞ジジイの「現状の抜作」と「今後の間抜」ヒートマップ用インデックス"
    curl -X 'POST' \
      'http://'$PUBLIC_IP'/aho_bakatare/heatmap/booo/' \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{"bakatare_ID":"B00001","JD_Number":"02"}'
    ```
  </details>   
* 動作中のコンテナを停止し、イメージを削除する
  <details><summary>./remove_container.sh</summary>
    
    ```bash
    CONTAINER_NAME=$1
    docker stop $CONTAINER_NAME-fastapi && docker rm -f $CONTAINER_NAME-fastapi
    docker rmi $(docker images $CONTAINER_NAME-fastapi --format "{{.ID}}")
    docker rmi -f $(docker images -q)
    docker ps -a && docker images
    ```
  </details>

### 初回登録
* AWS CLIの設定情報を確認
  ```bash
  cat ~/.aws/config
  ```
  <details><summary>実行結果</summary>
  
  ```bash
  [default]
  region = us-east-1
  aws_access_key_id = ABCDEFGHIJKLMNOPQ
  aws_secret_access_key = abcd123abcd123abcd123abcd123

  [profile bakaconf]
  region = us-east-1
  aws_access_key_id = ABCDEFGHIJKLMNOPQ
  aws_secret_access_key = abcd123abcd123abcd123abcd123

  [profile usprod]
  region = us-east-1
  aws_access_key_id = ABCDEFGHIJKLMNOPQ
  aws_secret_access_key = abcd123abcd123abcd123abcd123

  [profile prod]
  region = ap-northeast-1
  aws_access_key_id = ABCDEFGHIJKLMNOPQ 
  aws_secret_access_key = abcd123abcd123abcd123abcd123

  [profile dev]
  region = ap-northeast-1
  aws_access_key_id = IJKLMNOPQRSTUVW
  aws_secret_access_key = dfususow8754dd
  ```
  </detail>
* 認証トークンを取得し、レジストリに対して Docker クライアントを認証
  * リージョン：`バージニア北部`の場合
    ```bash
    AWS_ACOUNT_ID=12345678901 && REGION=us-east-1 && AWS_PROFILE=bakaconf && CONTAINER_NAME=foo_bakatare && KIND=fastapi && IMAGE_MAME=$CONTAINER_NAME'-'$KIND
    aws ecr get-login-password --region $REGION --profile $AWS_PROFILE | docker login --username AWS --password-stdin $AWS_ACOUNT_ID.dkr.ecr.us-east-1.amazonaws.com
    ```
    <details><summary>実行結果</summary>
    
    ```bash
    Login Succeeded
    ```
    <<details><summary>details</summary>
</details>

* Dockerコンテナをビルドし、コンテナイメージにタグを付与
  ```bash
  cd ~/aws/mongodb/ && docker ps -a && docker images && ./remove_container.sh $CONTAINER_NAME
  docker build -t $IMAGE_MAME -f Dockerfile_$CONTAINER_NAME .
  'docker tag '$IMAGE_MAME':latest '$AWS_ACOUNT_ID'.dkr.ecr.'$REGION'.amazonaws.com/'$IMAGE_MAME':latest'
  docker ps -a && docker images
  ```
* FastAPIサービスのDockerコンテナをポート80でローカル端末でテスト実行
  ```bash
  docker run -d -p 80:80 --name $IMAGE_MAME $IMAGE_MAME
  ```
  * ローカルURL : http://localhost/docs
* AWS ECRリポジトリを作成し、タグ付けしたコンテナイメージをプッシュ
  ```bash
  aws ecr create-repository --repository-name $IMAGE_MAME
  docker push $AWS_ACOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$IMAGE_MAME':latest'
  ```
  <details><summary>実行結果</summary>
    
  ```json
  {
    "repository": {
        "repositoryArn": "arn:aws:ecr:us-east-1:12345678901:repository/foo_bakatare-fastapi",
        "registryId": "12345678901",
        "repositoryName": "foo_bakatare-fastapi",
        "repositoryUri": "12345678901.dkr.ecr.us-east-1.amazonaws.com/foo_bakatare-fastapi",
        "createdAt": "2024-10-06T16:47:12.317000+09:00",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": false
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }
    }
  }
  ```
  ```bash
  The push refers to repository [12345678901.dkr.ecr.us-east-1.amazonaws.com/foo_bakatare-fastapi]
  f4e81d585f22: Pushed 
  e46ea3317667: Pushed 
  0326df620ed2: Pushed 
  6ddff48d9c6e: Pushed 
  5f70bf18a086: Pushed 
  6d835c0b5006: Pushed 
  9ce5156d8e4e: Pushed 
  7cda1b8c5bbf: Pushed 
  cf0e723ea047: Pushed 
  0a9ccad5eb69: Pushed 
  30bc2dab5899: Pushed 
  20d5b086fe88: Pushed 
  ba8e44410c8a: Pushed 
  8628259c120e: Pushed 
  e8b56a267ef1: Pushed 
  8325e8413ce3: Pushed 
  228e477f5903: Pushed 
  dd3bb83a5529: Pushed 
  5dd1f684416f: Pushed 
  3a8081ce85fa: Pushed 
  045d8b74bf0d: Pushed 
  25879f85bbb0: Pushed 
  6abe10f2f601: Pushed 
  latest: digest: sha256:f788e5906d33102f89921e6709122af205df824c2a798a16cb9e046c0f2630fa size: 5332
  ```
  </details>
* ECSでFargateを使用する【クラスター】を作成
  ```bash
  aws ecs create-cluster --cluster-name $CONTAINER_NAME-cluster --region $REGION
  ```
  <details><summary>実行結果</summary>
    
  ```json
  {
    "repository": {
        "repositoryArn": "arn:aws:ecr:us-east-1:12345678901:repository/foo_bakatare-fastapi",
        "registryId": "12345678901",
        "repositoryName": "foo_bakatare-fastapi",
        "repositoryUri": "12345678901.dkr.ecr.us-east-1.amazonaws.com/foo_bakatare-fastapi",
        "createdAt": "2024-10-06T16:47:12.317000+09:00",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": false
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }
    }
  }
  ```
  </details>
* ECSでFargateを使用する【タスク定義】を作成
  ```bash
  aws ecs register-task-definition \
    --family $CONTAINER_NAME-definition \
    --network-mode awsvpc \
    --requires-compatibilities FARGATE \
    --cpu "256" \
    --memory "512" \
    --execution-role-arn arn:aws:iam::$AWS_ACOUNT_ID':role/ecsTaskExecutionRole' \
    --container-definitions '[
      {
        "name": "'$CONTAINER_NAME'-container",
        "image": "'$AWS_ACOUNT_ID'.dkr.ecr.'$REGION'.amazonaws.com/'$IMAGE_MAME':latest",
        "essential": true,
        "portMappings": [
          {
            "containerPort": 80,
            "hostPort": 80
          }
        ]
      }
    ]' \
    --region $REGION
  ```
  <details><summary>実行結果</summary>
    
  ```json
  {
    "name": "foo_bakatare-container",
    "image": "12345678901.dkr.ecr.us-east-1.amazonaws.com/foo_bakatare-fastapi:latest",
            "environment": [],
            "mountPoints": [],
            "volumesFrom": [],
            "systemControls": []
        }
    ],
    "family": "foo_bakatare-definition",
    "executionRoleArn": "arn:aws:iam::12345678901:role/ecsTaskExecutionRole",
    "networkMode": "awsvpc",
    "revision": 1,
    "volumes": [],
    "status": "ACTIVE",
    "requiresAttributes": [
        {
            "name": "com.amazonaws.ecs.capability.ecr-auth"
        },
        {
            "name": "ecs.capability.execution-role-ecr-pull"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
        },
        {
            "name": "ecs.capability.task-eni"
        }
    ],
    "placementConstraints": [],
    "compatibilities": [
        "EC2",
        "FARGATE"
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "256",
    "memory": "512",
    "registeredAt": "2024-10-06T17:42:50.486000+09:00",
    "registeredBy": "arn:aws:iam::12345678901:user/T_Sameshima"
  }
  ```
  </details>
* ECS上に【サービス】を新規作成

|リージョン |クラスター名             |タスク定義ファミリー         |サービス名               |
|---------|-----------------------|--------------------------|-----------------------|
|$REGION  |$CONTAINER_NAME-cluster|$CONTAINER_NAME-definition|$CONTAINER_NAME-service|
|タスク実行ロール                                          |セキュリティグループID |プロトコル  |ポート範囲/ソース|
|arn:aws:iam::$AWS_ACOUNT_ID':role/ecsTaskExecutionRole'|sg-sodkoasdokosakdos0|HTTP / TCP|80/0.0.0.0/0|
|サブネット1|サブネット2|サブネット3|パブリックIPアドレス設定|
|subnet-jijadfisajiffs", "subnet-asfasfksaokfosakofkas"|"subnet-sfusfu8af8asf","subnet-fasf89sa89f8sa98f9"|"subnet-asff09sa0f90sa", "subnet-fsaf0jfoasjof|有効|

* コマンド
  ```bash
  aws ecs create-service \
    --cluster $CONTAINER_NAME-cluster \
    --service-name $CONTAINER_NAME-service \
    --task-definition $CONTAINER_NAME-definition \
    --desired-count 1 \
    --launch-type FARGATE \
    --network-configuration '{
      "awsvpcConfiguration": {
        "subnets": ["subnet-jijadfisajiffs", "subnet-asfasfksaokfosakofkas", "subnet-sfusfu8af8asf", "subnet-fasf89sa89f8sa98f9", "subnet-asff09sa0f90sa", "subnet-fsaf0jfoasjof"],
        "securityGroups": ["sg-sodkoasdokosakdos0"],
        "assignPublicIp": "ENABLED"
      }
    }' \
    --region $REGION
  ```
  <details><summary>実行結果</summary>
    
  ```json
  {
    "service": {
        "serviceArn": "arn:aws:ecs:us-east-1:12345678901:service/foo_bakatare-cluster/foo_bakatare-service",
        "serviceName": "foo_bakatare-service",
        "clusterArn": "arn:aws:ecs:us-east-1:12345678901:cluster/foo_bakatare-cluster",
        "loadBalancers": [],
        "serviceRegistries": [],
        "status": "ACTIVE",
        "desiredCount": 1,
        "runningCount": 0,
        "pendingCount": 0,
        "launchType": "FARGATE",
        "platformVersion": "LATEST",
        "platformFamily": "Linux",
        "taskDefinition": "arn:aws:ecs:us-east-1:12345678901:task-definition/foo_bakatare-definition:1",
        "deploymentConfiguration": {
            "deploymentCircuitBreaker": {
                "enable": false,
                "rollback": false
            },
            "maximumPercent": 200,
            "minimumHealthyPercent": 100
        },
        "deployments": [
            {
                "id": "ecs-svc/222222222222222",
                "status": "PRIMARY",
                "taskDefinition": "arn:aws:ecs:us-east-1:12345678901:task-definition/foo_bakatare-definition:1",
                "desiredCount": 0,
        :...skipping...
        {
            "service": {
                "serviceArn": "arn:aws:ecs:us-east-1:12345678901:service/foo_bakatare-cluster/foo_bakatare-service",
                "serviceName": "foo_bakatare-service",
                "clusterArn": "arn:aws:ecs:us-east-1:12345678901:cluster/foo_bakatare-cluster",
                "loadBalancers": [],
                "serviceRegistries": [],
                "status": "ACTIVE",
                "desiredCount": 1,
                "runningCount": 0,
                "pendingCount": 0,
                "launchType": "FARGATE",
                "platformVersion": "LATEST",
                "platformFamily": "Linux",
                "taskDefinition": "arn:aws:ecs:us-east-1:12345678901:task-definition/foo_bakatare-definition:1",
                "deploymentConfiguration": {
                    "deploymentCircuitBreaker": {
                        "enable": false,
                        "rollback": false
                    },
                    "maximumPercent": 200,
                    "minimumHealthyPercent": 100
                },
                "deployments": [
                    {
                        "id": "ecs-svc/222222222222222",
                        "status": "PRIMARY",
                        "taskDefinition": "arn:aws:ecs:us-east-1:12345678901:task-definition/foo_bakatare-definition:1",
                        "desiredCount": 0,
                        "pendingCount": 0,
                        "runningCount": 0,
                        "failedTasks": 0,
                        "createdAt": "2024-10-06T20:43:04.919000+09:00",
                        "updatedAt": "2024-10-06T20:43:04.919000+09:00",
                        "launchType": "FARGATE",
                        "platformVersion": "1.4.0",
                        "platformFamily": "Linux",
                        "networkConfiguration": {
                            "awsvpcConfiguration": {
                                "subnets": [
                                    "subnet-jijadfisajiffs",
                                    "subnet-asfasfksaokfosakofkas",
                                    "subnet-sfusfu8af8asf",
                                    "subnet-fasf89sa89f8sa98f9",
                                    "subnet-asff09sa0f90sa",
                                    "subnet-fsaf0jfoasjof"
                                ],
                                "securityGroups": [
                                    "sg-06dd2174e159caea2"
                                ],
                                "assignPublicIp": "ENABLED"
                            }
                        },
                        "rolloutState": "IN_PROGRESS",
                        "rolloutStateReason": "ECS deployment ecs-svc/222222222222222 in progress."
                    }
                ],
                "roleArn": "arn:aws:iam::12345678901:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS",
                "events": [],
                "createdAt": "2024-10-06T20:43:04.919000+09:00",
                "placementConstraints": [],
                "placementStrategy": [],
                "networkConfiguration": {
                    "awsvpcConfiguration": {
                        "subnets": [
                            "subnet-jijadfisajiffs",
                            "subnet-asfasfksaokfosakofkas",
                            "subnet-sfusfu8af8asf",
                            "subnet-fasf89sa89f8sa98f9",
                            "subnet-asff09sa0f90sa",
                            "subnet-fsaf0jfoasjof"
                        ],
                        "securityGroups": [
                            "sg-sodkoasdokosakdos0"
                        ],
                        "assignPublicIp": "ENABLED"
                    }
                },
                "schedulingStrategy": "REPLICA",
                "deploymentController": {
                    "type": "ECS"
                },
                "createdBy": "arn:aws:iam::12345678901:user/T_Sameshima",
                "enableECSManagedTags": false,
                "propagateTags": "NONE",
                "enableExecuteCommand": false
            }
    ```
    </details>