In Go, you can use the `GOOS` and `GOARCH` environment variables to specify the
target platform to build for.
Prerequisites:
- Docker Desktop or Docker Engine
Steps:
1. Create an empty directory and navigate to it:
```console
$ mkdir go-server
$ cd go-server
```
2. Create a base Dockerfile that builds the Go application:
```dockerfile
# syntax=docker/dockerfile:1
FROM golang:alpine AS build
WORKDIR /app
ADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .
RUN go build -o server .
FROM alpine
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]
```
This Dockerfile can't build multi-platform with cross-compilation yet. If
you were to try to build this Dockerfile with `docker build`, the builder
would attempt to use emulation to build the image for the specified
platforms.
3. To add cross-compilation support, update the Dockerfile to use the
pre-defined `BUILDPLATFORM` and `TARGETPLATFORM` build arguments. These
arguments are automatically available in the Dockerfile when you use the
`--platform` flag with `docker build`.
- Pin the `golang` image to the platform of the builder using the
`--platform=$BUILDPLATFORM` option.
- Add `ARG` instructions for the Go compilation stages to make the
`TARGETOS` and `TARGETARCH` build arguments available to the commands in
this stage.
- Set the `GOOS` and `GOARCH` environment variables to the values of
`TARGETOS` and `TARGETARCH`. The Go compiler uses these variables to do
cross-compilation.
{{< tabs >}}
{{< tab name="Updated Dockerfile" >}}
```dockerfile
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /app
ADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o server .
FROM alpine
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]
```
{{< /tab >}}
{{< tab name="Old Dockerfile" >}}
```dockerfile
# syntax=docker/dockerfile:1
FROM golang:alpine AS build
WORKDIR /app
ADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .
RUN go build -o server .
FROM alpine
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]
```
{{< /tab >}}
{{< tab name="Diff" >}}
```diff
# syntax=docker/dockerfile:1
-FROM golang:alpine AS build
+FROM --platform=$BUILDPLATFORM golang:alpine AS build
+ARG TARGETOS
+ARG TARGETARCH
WORKDIR /app
ADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .
-RUN go build -o server .
+RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o server .
FROM alpine
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]
```
{{< /tab >}}
{{< /tabs >}}
4. Build the image for `linux/amd64` and `linux/arm64`:
```console
$ docker build --platform linux/amd64,linux/arm64 -t go-server .
```
This example has shown how to cross-compile a Go application for multiple
platforms with Docker builds. The specific steps on how to do cross-compilation
may vary depending on the programming language you're using. Consult the
documentation for your programming language to learn more about cross-compiling
for different platforms.
> [!TIP]
> You may also want to consider checking out
> [xx - Dockerfile cross-compilation helpers](https://github.com/tonistiigi/xx).
> `xx` is a Docker image containing utility scripts that make cross-compiling with Docker builds easier.