Introduction to Docker multi stage builds for GO

With the advent of docker multi stage builds we can now perform all steps to build our GO docker container so that we ship a lightweight container to your choice of registry. Now there are many ways to perform multi stage builds and this is just an example below that you can use in a pipeline. One topic currently gaining traction is creating a Golden image. If there is enough interest we research and see how to build those.


Example Dockerfile

# Create your GO src files
FROM golang:alpine as go_src
RUN apk add --no-cache git gcc 
RUN mkdir /app
WORKDIR /app
COPY . .

# GO BUILD 
RUN CGO_ENABLED=0 GOOS=linux go build -a
# GO TEST
RUN go test -cover $(go list ./... |grep -v /ntgrtn)

# GO SECURITY 
FROM alpine:latest AS go_security 
RUN apk update
RUN apk add -U --no-cache ca-certificates
RUN adduser -D -g '' appuser

# GO FINAL
FROM scratch AS final
ARG env
WORKDIR /app
COPY --from_go_security /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=go_security /etc/password /etc/passwd
USER appuser
COPY --from=go_src /app/myapp_name .
EXPOSE 6000
CMD ["/myapp_name"] 

Lets break down what we are building GO SRC

# Create your GO src files
FROM golang:alpine as go_src
RUN apk add --no-cache git gcc musl-dev
RUN mkdir /app
WORKDIR /app
COPY . .

First we are getting golang:alpine from docker repo and labeling it as go_src
Then we run apk to add any libraries that we need (configure yours as needed)
We run mkdir /app to create a directory to work in
WORKDIR sets the /app directory
COPY . . is copying in your go files, reference compiling go for modules in other docs

Next we have GO BUILD

# GO BUILD 
RUN CGO_ENABLED=0 GOOS=linux go build -a
# GO TEST
RUN go test -cover $(go list ./... |grep -v /(name of your test coverages)

Here we run CGO enabled set to 0 and GOOS to enable linux output binaries 
It's always a good idea to do some form of test coverage

Then it’s GO SECURITY

# GO SECURITY 
FROM alpine:latest AS go_security 
RUN apk update
RUN apk add -U --no-cache ca-certificates
RUN adduser -D -g '' appuser
This will probably be ever changing as docker is iterated on, but in general 
one of the benefits of docker is being able to just build a container on what you need 
and bring in just the bare minimum you need to run your container
So here we run apk update to grab any updates
We run apk add your ca-certificates (we will do a post on this in the future)
Then we add a user for our application to run with that is not root (read Docker security best practices)

Finally we have GO FINAL

# GO FINAL
FROM scratch AS final
ARG env
WORKDIR /app
COPY --from_go_security /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=go_security /etc/password /etc/passwd
USER appuser
COPY --from=go_src /app/myapp_name .
EXPOSE 6000
CMD ["/myapp_name"] 

Using the FROM scratch means we are starting with a bare minimum empty container 
Here we bring in our previous components from GO Security to use in this final stage 
With ARG env we are setting env
Set our working directory to /app
With both copy commands we are bringing in the ca-certs and /etc/passwd so that we can use it in our scratch container
We set the user to appuser
Then copy forward our application code
We expose our port 6000 (or whatever port you require)
Using the CMD we set our runtime out of our application path. 

Happy docker building!

Leave a Reply

Your email address will not be published. Required fields are marked *