Paul BradleySolutions Architect & Software Developer


Published:

Go - Compiling Code in a Docker Image

Using a docker image to compile your Go code with the latest version of Go.

midjourney ai - A samurai with pitch black skin standing in front of a deserted city

Why use Docker to compile Go code?

I’m using a Ubuntu LTS release for my main development machine and the version of Go that is included with the package manger is version 1.13.8. I had a need to compile a program using the latest version of Go which at the time of writing this is 1.19.3.

I could have updated my local development machine, but I wanted to see if I could use Docker to compile and compress my executable using the official Golang Image as a starting point.

Writing the Dockerfile

Below is the Dockerfile I came up with to compile my Lambda functions. Starting from the official 1.19.3 Golang Image I then update the Alpine packages and install Git, UPX and gcc.

I don’t like using modules, so the environment variable GO111MODULE=off forces Go behave in the GOPATH way, even outside of GOPATH. The other two environment variables allows me to compile the function for the ARM/Graviton Architecture.

FROM golang:1.19.3-alpine AS builder

# update the packages and install
# git, upx and gcc
RUN apk update
RUN apk add --no-cache git
RUN apk add --update bash
RUN apk add --update upx
RUN apk add --update gcc musl-dev

# set environment variables to control
# which architecture to target
ENV GO111MODULE=off
ENV GOOS=linux
ENV GOARCH=arm64

# install Go packages required to build our project
RUN go get github.com/aws/aws-lambda-go/events; exit 0
RUN go get github.com/aws/aws-lambda-go/lambda; exit 0

# make a directory called builder and copy
# our Go source code into the directory
RUN mkdir -p /go/src/builder
ADD ./ /go/src/builder

# compile the code and then compress the
# executable with UPX to reduce its size
RUN cd /go/src/builder && \
    go build -tags="lambda.norpc" \
             -ldflags="-w -s" \
             -o /go/bin/bootstrap *.go && \
    cd /go/bin/ && upx -9 bootstrap

After defining the environment variables, we install the Go packages needed for the project. Docker’s caching system means that these files need only to be downloaded once. Subsequent runs of the same Dockerfile will start from the ADD command, which copies our source code to the Docker image.

Lastly, we use the Docker RUN command to build the project and compress the executable.

Using the Dockerfile to compile Go code

Below is an example showing the sequence of Docker commands used to:

docker build -t lambda -f ../build.Dockerfile .
docker run --name "lambda" lambda /bin/bash
docker cp lambda:/go/bin/bootstrap ./bootstrap
docker rm lambda
zip -9 main.zip bootstrap