4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[AWS] S3+CloudFront に Deploy する buildspec(CodeBuild)

Last updated at Posted at 2022-01-18

AWS で SPA などの静的コンテンツを公開する際、S3 + CloudFront という構成がよくある形。

その構成でデプロイする場合、 S3 にファイルを配置して CloudFront のキャッシュを削除する必要があるが、
CodeDeployS3 へのデプロイに対応しておらず、
CodePipelineS3 へのファイル配置は可能であるものの CloudFront のキャッシュ削除が出来ない。
CodeBuild で実施するのがベターと考えた。

というわけで、そのための buildspec が以下。

buildspec

buildspec.yml
version: 0.2

phases:
  pre_build:
    commands:
      - echo "# Deoloyment Info"
      - echo "S3_BUCKET_NAME = ${S3_BUCKET_NAME}"
      - echo "CLOUDFRONT_ID  = ${CLOUDFRONT_ID}"
      - echo "CLOUDFONT_INVALIDATION_PATHS = ${CLOUDFONT_INVALIDATION_PATHS}"
  # build:
  #   commands:
  #     # - command
  post_build:
    commands:
      - echo "# Build completed on `date`"
      - ls -la
      - echo "# Update S3-Objects ..."
      - aws s3 sync ./ s3://${S3_BUCKET_NAME} --exact-timestamps
      - sleep 10
      - echo "# Invalidate CloudFront-Cache"
      - RESPONSE=`aws cloudfront create-invalidation --distribution-id "${CLOUDFRONT_ID}" --paths ${CLOUDFONT_INVALIDATION_PATHS}`
      - INVALIDATION_ID=`echo ${RESPONSE} | jq -r '.Invalidation.Id'`
      - echo "Invalidation.Id = ${INVALIDATION_ID}"
      - STATUS="";
        while [ "${STATUS,,}" != "completed" ]; do
          sleep 5;
          RESPONSE=`aws cloudfront get-invalidation --distribution-id "${CLOUDFRONT_ID}" --id "${INVALIDATION_ID}"`;
          STATUS=`echo ${RESPONSE} | jq -r '.Invalidation.Status'`;
          echo "status = ${STATUS}";
        done
      - echo "# Remove Old S3-Objects"
      - aws s3 sync ./ s3://${S3_BUCKET_NAME} --delete

処理概要

  1. ファイルを aws s3 sync で S3 バケットにコピー。追加/更新のみ。
  2. CloudFront の キャッシュを削除。
  3. 不要になったファイルを aws s3 sync --delete で S3 バケットから削除。

前提

  • S3 に配置するファイル群は CodeBuild 内のデフォルトディレクトリに存在する前提。
    そうでない場合は aws s3 sync のコピー元を変更する。

CodeBuild 環境変数

  • S3_BUCKET_NAME ... ファイルのデプロイ先となる S3 バケット名。
  • CLOUDFRONT_ID ... AWSが自動生成する CloudFront ID。13文字くらいのランダム文字列。
  • CLOUDFONT_INVALIDATION_PATHS ... キャッシュ削除の対象とするパス。スペース区切りで複数指定可。

CodeBuild の IAM-Role Policy

CodeBuild の IAM-Role に付与するポリシー。

IAM-Policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "s3",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::<BUCKET_NAME>",
                "arn:aws:s3:::<BUCKET_NAME>/*"
            ],
            "Action": [
                "s3:Get*",
                "s3:List*",
                "s3:PutObject",
                "s3:CopyObject",
                "s3:DeleteObject"
            ]
        },
        {
            "Sid": "cloudfront",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:cloudfront::<ACCOUNT_ID>:distribution/<CLOUDFRONT_ID>"
            ],
            "Action": [
                "cloudfront:*Invalidation"
            ]
        }
    ]
}

S3に対するアクションはもう少し減らせる。
AWSナレッジセンターのこちらの記事 では s3 sync のためには、ListObjectsV2 CopyObject GetObject PutObject が必要と書いているが、 --delete を使用する場合は DeleteObject も必要。

4
6
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
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?