Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker scratch image not showing up as arm64

Tags:

linux

docker

go

arm

I'm building a Docker image for multiple architectures (amd64 and arm64 - both on Linux). I'm using a multistage build - this means using go-alpine image as a builder (to compile my Go source code into an executable), and then copying the executable to a smaller secondary image.

Initially, I was copying the compiled program into an Alpine image, but I decided to switch to a scratch image (because of the security benefit) - this involved changing my build command so that the resultant executable is statically linked. My Dockerfile is now:

FROM golang:1.16 AS builder
WORKDIR /go/src/
RUN go get -d -v ./...
COPY . .
RUN env ${opts} go build -a -installsuffix cgo -o app .

FROM scratch
WORKDIR /root/
COPY --from=builder /go/src/app .
CMD ["./app"]

When I build for amd64, I run docker build --build-arg opts="CGO_ENABLED=0 GOOS=linux GOARCH=amd64" -t myuser/example:amd64 . - if I inspect this image, it shows "Architecture": "amd64" as expected.

When I build for arm64, I run docker build --build-arg opts="CGO_ENABLED=0 GOOS=linux GOARCH=arm64" -t myuser/example:arm64 . - if I inspect this image, it shows "Architecture": "amd64" - which isn't what I want.

If I compile the Go code locally by running CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build, and then I run file on the compiler output, it shows that the compiled output is arm64. I assume that the issue is therefore a result of Docker pulling an amd64 base image (since my PC is x86), but I can't figure out how to fix the issue.

like image 665
ChardeeMacdennis Avatar asked Oct 21 '25 22:10

ChardeeMacdennis


2 Answers

Because you stand on AMD machine and docker will default pull AMD golang image to build your project. There's several way to fix it, but this case I suggest use --platform=$BUILDPLATFORM

https://docs.docker.com/buildx/working-with-buildx/

So, your Dockerfile look like:

FROM --platform=$BUILDPLATFORM golang:1.16 AS builder
ARG BUILDPLATFORM
WORKDIR /go/src/
RUN go get -d -v ./...
COPY . .
RUN env ${opts} go build -a -installsuffix cgo -o app .

FROM --platform=$BUILDPLATFORM scratch
WORKDIR /root/
COPY --from=builder /go/src/app .
CMD ["./app"]

And the build command in your local:

docker build --build-arg BUILDPLATFORM=linux/arm64 --build-arg opts="CGO_ENABLED=0 GOOS=linux GOARCH=arm64" -t myuser/example:arm64 .

But if you're building your Golang image with Github Action or CircleCI, please checkout these blog post below

Golang multi-arch image with Github Action https://namiops.medium.com/golang-multi-arch-docker-image-with-github-action-b59a62c8d2bd

Golang arm image with CircleCI https://namiops.medium.com/golang-arm64-docker-image-with-circleci-arm-machine-8bebf2151b92

like image 134
namiops Avatar answered Oct 23 '25 12:10

namiops


The snippets you shared are cross-compiling your Go binary, but like you pointed out, are still using an amd64 base image. To do this, you will need to build a docker container for multiple platforms:

https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/

The example is something like:

docker buildx build \
--platform linux/arm64/v8,linux/amd64 \ 
--tag your-username/multiarch-example:buildx-latest .

Using the docker platform route, you shouldn't need to use go-multiarch building since the go tool should infer the platform its building for.

As an alternative, you could cross-compile your binary on your host, and then have a docker image for each platform that is based off of the scratch image for that architecture and just copies your executable in.

like image 36
mrosales Avatar answered Oct 23 '25 11:10

mrosales



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!