Skip to content

Instantly share code, notes, and snippets.

@alexturek
Last active January 15, 2025 22:47
Show Gist options
  • Save alexturek/73375080c459d680ca1a0039a667d04e to your computer and use it in GitHub Desktop.
Save alexturek/73375080c459d680ca1a0039a667d04e to your computer and use it in GitHub Desktop.
Publish AWS ECR multiplatform docker images in Github Actions

Publish AWS ECR multiplatform docker images in Github Actions

In Github actions

  1. Get an AWS login somehow. See https://github.com/aws-actions/configure-aws-credentials. Steps:
     - name: Configure AWS credentials
       uses: aws-actions/configure-aws-credentials@v4
       with:
         audience: sts.amazonaws.com
         aws-region: YOUR REGION HERE
         role-to-assume: ARN GOES HERE
  2. Install the AWS ECR credential helper in CI
    sudo apt update && sudo apt install amazon-ecr-credential-helper
    mkdir -p ~/.docker
    touch ~/.docker/config.json
    cat ~/.docker/config.json
    echo '{
    "credsStore": "ecr-login"
    }' > ~/.docker/config.json
  3. Build 1+ docker images for different platforms. Ideally you use Docker's buildx plugin, maybe needing QEMU installed, to just build two images + the manifest to reference them. See Docker's docs. Just use Github's action for this and save yourself a headache. Make sure to add the --platform args via with: platforms: linux/amd64,linux/arm64
  4. If you can't do that, because e.g. you need to build with two different contexts or something, you're going to need to
    1. build two images using different --platform args
      docker buildx build . \
        --platform linux/$ARCHITECTURE \ # "arm64" (mac M-class chips or Graviton instances) or "amd64" (most computers)
        -t ${DOCKER_IMAGE_NAME} \        # Your docker image[:tag]
        --progress plain \               # Easier for CI
        --output type=docker \           # I don't know why this is here but I ended up needing it
        --target $DOCKER_BUILD_TARGET    # for multistage builds
    2. Build a manifest from scratch, referencing both images, and then push that to your docker repo
      ECR_IMAGE=public.ecr.aws/SOMEURL
      LOCAL_TAG=my-local-docker-image
      ARM_FOR_MAC=arm64
      INTEL_FOR_EVERYTHING_ELSE=amd64
      
      docker images
      
      docker tag ${LOCAL_TAG}-${INTEL_FOR_EVERYTHING_ELSE} ${ECR_IMAGE}:latest-${INTEL_FOR_EVERYTHING_ELSE}
      docker tag ${LOCAL_TAG}-${ARM_FOR_MAC} ${ECR_IMAGE}:latest-${ARM_FOR_MAC}
      
      docker push ${ECR_IMAGE}:latest-${INTEL_FOR_EVERYTHING_ELSE}
      docker push ${ECR_IMAGE}:latest-${ARM_FOR_MAC}
      
      docker manifest rm ${ECR_IMAGE} || echo "Already no local manifest"
      
      docker manifest create --amend ${ECR_IMAGE} \
        ${ECR_IMAGE}:latest-${INTEL_FOR_EVERYTHING_ELSE} \
        ${ECR_IMAGE}:latest-${ARM_FOR_MAC}
      
      docker manifest inspect ${ECR_IMAGE
      docker manifest push ${ECR_IMAGE}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment