Totally static Go builds

April 23, 2019

How to create static Go builds

Static Go builds are great for quick and easy deploy and for running in Docker containers.

CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' .

How to reduce the binary size

You can reduce the binary size by compressing it using UPX.

upx --best [binary file]

or

upx --ultra-brute [binary file]

to test if the binary is OK

upx -t [binary file]

Bonus: static build plus binary size shrink in docker using multi-stage

############################
# STEP 1 build executable binary
############################
FROM golang:1.12-alpine as builder

# Install Git + UPX.
RUN apk update && \
 apk add --no-cache upx git ca-certificates tzdata && \
 update-ca-certificates && \
 addgroup --system app && adduser -S -G app app

# Set the Current Working Directory inside the container
WORKDIR $GOPATH/src/<domain>/<username>/<project>

# Copy everything from the current directory inside the container
COPY . .

# Build the binary (using go mod) and execute UPX
RUN GO111MODULE=on go mod vendor && \
 CGO_ENABLED=0 GOOS=linux \
 go build -a -ldflags '-w -extldflags "-static"' -o /tmp/<app-binary> ./cmd/. && \
 upx --ultra-brute -q /tmp/<app-binary> && \
 upx -t /tmp/<app-binary>

############################
# STEP 2 build a small image
############################
FROM scratch

# Import from builder.
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /etc/passwd /etc/passwd
# Copy our static executable
COPY --from=builder /tmp/<app-binary> /home/app/<app-binary>

# Use the unprivileged user.
USER app

# Run the binary.
ENTRYPOINT ["/home/app/<app-binary>"]

where:

  • <domain> is the name of your company or group (i.e. github.com)
  • <username> is your name (i.e. lucasepe)
  • <project> is the name of your project (i.e. magick-pot)
  • <app-binary> is the name of your app (i.e. mpot)