🌊

33.ECRとECS FargateをCloudFormationで動かしてみる試み

2024/08/23に公開

0. やりたいこと

  • 以前作ったECS FargateのCloudFormationは、テンプレートファイル外でECRのリポジトリを作成
  • そのため、テンプレートファイル内でECRのリポジトリを作成したい
  • あわせて、ライフサイクルポリシーもテンプレート内で定義したい

https://zenn.dev/jksan/articles/19_u_the_kyoto
https://zenn.dev/jksan/articles/22_u_the_ecr_lifecycle_policy

1. ファイル修正

  • ECRのリソースを追加
kyoto-template.yaml
  # ECR Repository
  ECRRepository:
    Type: AWS::ECR::Repository
    Properties:
      RepositoryName: kyoto-repository
      ImageScanningConfiguration:
        scanOnPush: true
      LifecyclePolicy:
        LifecyclePolicyText: |
          {
            "rules": [
              {
                "rulePriority": 1,
                "description": "Expire untagged images older than 1 days",
                "selection": {
                  "tagStatus": "untagged",
                  "countType": "sinceImagePushed",
                  "countUnit": "days",
                  "countNumber": 1
                },
                "action": {
                  "type": "expire"
                }
              }
            ]
          }
      Tags:
        - Key: Stack
          Value: kyoto
  • Task DefinitionのImageの参照先を上記で作成したリポジトリに変更
kyoto-template.yaml
  # ECS Task Definition
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: kyoto-task
      Cpu: '256'
      Memory: '512'
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      ExecutionRoleArn: !GetAtt ECSExecutionRole.Arn
      ContainerDefinitions:
        - Name: kyoto-container
-          Image: <image>
+          Image: !Sub "${ECRRepository.RepositoryUri}:latest"

2. Stackの作成

# stackの作成(10分程度)
$ aws cloudformation create-stack \
	--profile <my-profile> \
	--region us-east-1 \
	--stack-name kyoto \
	--template-body file://kyoto-template.yaml \
	--capabilities CAPABILITY_IAM

確認

$ aws ecr get-lifecycle-policy \
	--profile <my-profile> \
	--region us-east-1 \
	--repository-name kyoto-repository
{
    "registryId": "xxx",
    "repositoryName": "kyoto-repository",
    "lifecyclePolicyText": "{\"rules\":[{\"rulePriority\":1,\"description\":\"Expire untagged images older than 1 days\",\"selection\":{\"tagStatus\":\"untagged\",\"countType\":\"sinceImagePushed\",\"countUnit\":\"days\",\"countNumber\":1},\"action\":{\"type\":\"expire\"}}]}",
    "lastEvaluatedAt": "1970-01-01T09:00:00+09:00"
}

3. ECRにイメージをPush

  • まだCI/CDがないのでコマンドから実行
# ログイン
$ aws ecr get-login-password \
	--profile <my-profile> \
	--region us-east-1 | \
	docker login --username AWS --password-stdin <account-id>.dkr.ecr.<your-region>.amazonaws.com

# 作ったイメージにタグ付け
$ docker tag kyoto:latest <account-id>.dkr.ecr.<your-region>.amazonaws.com/kyoto:latest

# ECRにイメージをプッシュ
$ docker push <account-id>.dkr.ecr.<your-region>.amazonaws.com/kyoto:latest

4. 確認

  • 確認のために適当にファイルを更新、イメージを更新して、repositoryに2つのイメージを用意
main.go
- return c.JSON(http.StatusOK, "OK")
+ return c.JSON(http.StatusOK, "OK!")
# イメージのビルド
$ docker build -t kyoto . --no-cache

# 作ったイメージにタグ付け
$ docker tag kyoto:latest <account-id>.dkr.ecr.<your-region>.amazonaws.com/kyoto:latest

# ECRにイメージをプッシュ
$ docker push <account-id>.dkr.ecr.<your-region>.amazonaws.com/kyoto:latest

2つイメージが存在することを確認

$ aws ecr describe-images \
	--profile <my-profile> \
	--region us-east-1 \
	--repository-name kyoto-repository
{
    "imageDetails": [
        {
            "registryId": "xxx",
            "repositoryName": "kyoto-repository",
            "imageDigest": "sha256:13003753875e2c42735762fdf91101b08846b884a2aacb3106fe6a812862509f",
            "imageSizeInBytes": 8084683,
            "imagePushedAt": "2024-08-21T08:52:01+09:00",
            "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "artifactMediaType": "application/vnd.docker.container.image.v1+json",
            "lastRecordedPullTime": "2024-08-21T08:52:17.317000+09:00"
        },
        {
            "registryId": "xxx",
            "repositoryName": "kyoto-repository",
            "imageDigest": "sha256:24ffa5c9d001f3fbdb72e1974b9921cc5fa2de21c3cac6599546a417f70a8545",
            "imageTags": [
                "latest"
            ],
            "imageSizeInBytes": 8084664,
            "imagePushedAt": "2024-08-21T08:57:39+09:00",
            "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "artifactMediaType": "application/vnd.docker.container.image.v1+json"
        }
    ]

1日後、イメージが消えていることの確認

$ aws ecr describe-images \
	--profile <my-profile> \
	--region us-east-1 \
	--repository-name kyoto-repository

結果

  • しっかり24時間後というわけではなく、大体24時間周期で実行される

備考

  • stackを消そうと思ったらこんなメッセージ出てた
Resource handler returned message: "The repository with name 'kyoto-repository' in registry with id 'xxx' cannot be deleted because it still contains images (Service: Ecr, Status Code: 400, Request ID: 6d224bed-b7ae-407a-9d9f-1f9e89d8616a)" (RequestToken: eb100f39-9848-1509-881e-fbe6f427d99b, HandlerErrorCode: GeneralServiceException)

おまけ

  • ほぼ1日Stackを作っただけの状態で発生した金額
    • $1.20
    • 為替を150円/$として 1.20 x 150 = 180円

Discussion