Small docker images for Go applications
Docker is a tool to containerise applications, it allows you to have a consistent environment to build and run your application locally or in production helping to mitigate any potential issues that can arise from differences in environments and conform to dev/prod parity.
When building docker images for Go applications, you can use the official golang image as a base image, once you have added your code and depenedencies the final image can be quite large.
As go is a compiled language we can use docker multi-stage builds to keep the final image size down, this is helpful when your cloud provider charges by storage like AWS ECR.
Here is an example dockerfile for a go application:
FROM golang:1.22
WORKDIR /usr/src/app
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
RUN go build -v -o /usr/local/bin/app ./cmd/app/main.go
EXPOSE 8080
CMD ["app"]
it’s 1gb in size.
A multi-stage build allows us to use the go image golang:1.22
to build our application,
then another image to run the application.
FROM golang:1.22 as buildStage
WORKDIR /appdir
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -v -o /usr/local/bin/myapp ./cmd/app/main.go
FROM alpine:latest
WORKDIR /
COPY --from=buildStage /usr/local/bin/myapp /
EXPOSE 8080
CMD ["/myapp"]
The first FROM
statement imports the go image and names it buildStage
,
we then build the application, the second FROM
statement imports the alpine image which
is a small linux image at only 5mb, we then copy the built application from the buildStage
image to the alpine image using COPY --from=buildStage
.
The final image size in this case is on 15mb.