AWS ECR multiarch containers and Go

David Gamba
version 1.0, 2023-03-08 #docker #aws_ecr #go

Note
For this example I am using a personal ECR repo where I put multiple images so adjust the tagging accordingly.

Before adjusting my Dockerfile to use multiarch I was building for ARM64 and getting the following error on execution:

standard_init_linux.go:228: exec user process caused: exec format error

The Dockerfile

This example clones a repo, and builds a Go binary using the GOARCH=${arch} ENV var:

ARG arch
FROM --platform=linux/${arch} golang:1.20.1 as builder

WORKDIR /workdir

ENV CFSSL_VERSION=v1.6.3

RUN git clone https://github.com/cloudflare/cfssl_trust.git /etc/cfssl && \
    git clone https://github.com/cloudflare/cfssl.git --branch ${CFSSL_VERSION} && \
    cd cfssl && \
    GOOS=linux GOARCH=${arch} go build -ldflags "-s -w -X github.com/cloudflare/cfssl/cli/version.version=${CFSSL_VERSION}" -o bin/cfssl ./cmd/cfssl

FROM --platform=linux/${arch} ubuntu:22.04

WORKDIR /workdir

COPY --from=builder /workdir/cfssl/bin/* /usr/bin/
COPY --from=builder /etc/cfssl /etc/cfssl

COPY ./server/ca-key.pem .
COPY ./server/ca.pem .

COPY ./server/config.json .
COPY ./docker-entrypoint.sh .

EXPOSE 8080

ENTRYPOINT ["/workdir/docker-entrypoint.sh"]
Note
Both containers, not just the builder need to have the --platform flag.

The build commands

	docker build -t xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-amd64  --build-arg arch=amd64 .
	docker build -t xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-arm64  --build-arg arch=arm64 .

	aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin xxx.dkr.ecr.us-west-2.amazonaws.com

	docker push xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-amd64
	docker push xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-arm64

	docker manifest create xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3 \
		xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-amd64 \
		xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-arm64 || true

	docker manifest annotate --arch amd64 xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3 \
      xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-amd64
	docker manifest annotate --arch arm64 xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3 \
      xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3-arm64

	docker manifest push xxx.dkr.ecr.us-west-2.amazonaws.com/dgamba:cfssl-1.6.3-3
Note
I needed to push the individual images before I could create the manifest.

Running amd64 images on MacOS M1

You have 2 options:

export DOCKER_DEFAULT_PLATFORM=linux/amd64

or

docker run --platform linux/amd64 -d -t ubuntu:22.04

Or you can mix them ;-)

DOCKER_DEFAULT_PLATFORM=linux/amd64 docker run --platform linux/amd64 -d -t ubuntu:22.04
Note
Keep in mind you might need to delete your images if they are already downloaded:
docker image rm <image>