💪

CodeBuild で Buildx を使ってクロスプラットフォームビルドを行う

2021/12/02に公開

AWS Fargate が Graviton2 に対応しました

AWS Fargate が Graviton2 に対応しました

CodeBuild でクロスプラットフォームビルドを行い、ARM プロセッサで Fargate タスクを動かします。

CodeBuild で Buildx を利用する

既に CodeBuild は Graviton2 に対応しています
そのため、Graviton2 の CodeBuild でイメージをビルドし、Graviton2 対応の Fargate で動作させることは簡単です。

しかし、同じイメージを Fargate で Graviton2 が利用できないリージョンでも動かしたかったため、アーキテクチャ毎にビルド用の CodeBuild を用意するのもナンセンスに感じました。
そのため、x86_64 の CodeBuild で x86_64 向けと arm64 向けのイメージをビルドすることにしました。ところが、残念ながら CodeBuild は現時点では Buildx をサポートしていません
これに対応するため、install フェーズで最新の buildx をインストールしています。

また、ECR は Docker マニフェストリストの作成・プッシュによるマルチアーキテクチャイメージに対応しています
これにより、同じイメージ名、イメージタグで複数のアーキテクチャの一意なイメージを取り扱うことができます。

下記にサンプルの buildspec.yml を示します。

buildspec.yml
phases:
  install:
    commands:
      # CodeBuild does not support Docker Buildx.
      # SEE ALSO: https://github.com/aws/aws-codebuild-docker-images/pull/379
      - BUILDX_BINARY_URL=$(curl -sLo - https://api.github.com/repos/docker/buildx/releases/latest | jq '.assets[] | select(.browser_download_url | contains("linux-amd64")).browser_download_url' -r)
      - mkdir -p ~/.docker/cli-plugins
      - curl -sL $BUILDX_BINARY_URL -o ~/.docker/cli-plugins/docker-buildx
      - chmod +x ~/.docker/cli-plugins/docker-buildx
      - docker run --privileged --rm tonistiigi/binfmt --install amd64,arm64

  pre_build:
    commands:
      - COMMIT_ID=${CODEBUILD_RESOLVED_SOURCE_VERSION:0:8}
      - AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
      - REGISTRY_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
      - IMAGE_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_NAME:$COMMIT_ID

  build:
    commands:
      - |
        for arch in amd64 arm64; do
          docker buildx build . -t $IMAGE_URI-$arch --platform linux/$arch --load
        done

  post_build:
    commands:
      - aws ecr get-login-password | docker login --username AWS --password-stdin $REGISTRY_URI
      - |
        for arch in amd64 arm64; do
          docker push $IMAGE_URI-$arch
        done

      # Pushing a multi-architecture image.
      # SEE ALSO: https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-multi-architecture-image.html
      - docker manifest create $IMAGE_URI $IMAGE_URI-amd64 $IMAGE_URI-arm64
      - |
        for arch in amd64 arm64; do
          docker manifest annotate $IMAGE_URI $IMAGE_URI-$arch --arch $arch
        done
      - docker manifest push $IMAGE_URI

      - printf '[{"name":"IMAGE_URI","imageUri":"$IMAGE_URI"}]' | envsubst | tee imagedefinitions.json
      - printf '{"ImageURI":"$IMAGE_URI"}' | envsubst | tee imageDetail.json

その他の注意点

タスク定義ファイルを AWS CLI で aws ecs register-task-definition する場合、AWS CLI v1 は runtimePlatform 属性に対応していません。
CodeBuild の al2/standard/3.0 を使用している場合、現時点では AWS CLI v1 なので注意しましょう。

"runtimePlatform": { "cpuArchitecture": "ARM64" },

Discussion