How to build lightweight docker container for Go app

Hello! Today i want to show you how to create fast building and lightweight docker image with Go onboard.

First of all, you need to create Dockerfile in root of your project, example of how it can be look like is below:

# Lightweight alpine OS, weight only 5mb, everything else is Go environment
FROM golang:1.9.2
# Workdir is path in your docker image from where all your commands will be executed
WORKDIR /go/src/github.com/centrypoint/refrigerator/back/go/main
# Add all from your project inside workdir of docker image
ADD . /go/src/github.com/centrypoint/refrigerator/back/go/main
# Then run your script to install dependencies and build application
RUN ./install-deps.sh && go build
# Next start another building context
FROM alpine:latest
# Copy only build result from previous step to new lightweight image
COPY --from=0 /go/src/github.com/centrypoint/regrigerator/back/go/main/main .
# Expose port for access to your app outside of container
EXPOSE 8080

# Starting bundled binary file
CMD [ "./main" ]

As you see, it uses alpine-go based image, which is super small, then execute all preparing operations for setup building environment, and than build, clean and prepare to run image.

Second FROM will create new building context and all your artifacts will be left behind in old context, from which you can copy only resulting binary file to your new image.

Result is just awesome, resulting size depends on size of your project, but anything else will cost only 5–10 mb of memory! So my image weight only 11.5 mb :)

So when you run from root project directory docker build --rm -f Dockerfile -t 'name-of-your-image' . You must see something similiar:

Sending build context to Docker daemon   38.4kB
Step 1/9 : FROM ataraev/golang-alpine-git:latest
---> 304f50dd83e4
Step 2/9 : WORKDIR /go/src/github.com/centrypoint/refrigerator/back/go/main
---> Using cache
---> 3b249f8775dd
Step 3/9 : ADD . /go/src/github.com/centrypoint/refrigerator/back/go/main
---> a4bbbf8f907e
Step 4/9 : RUN ./install-deps.sh && go build && find . -type f ! -name 'main' -delete && rm -rf db
---> Running in 04b2a4985f30
---> 1c1e900fd4e9
Removing intermediate container 04b2a4985f30
Step 5/9 : FROM alpine:latest
---> e21c333399e0
Step 6/9 : WORKDIR /root/
---> Using cache
---> f8778d2c6733
Step 7/9 : COPY --from=0 /go/src/github.com/centrypoint/refrigerator/back/go/main/main .
---> 4590efaaf68b
Step 8/9 : EXPOSE 8080
---> Running in eea55bb99b7b
---> 2fcd14cf3ba5
Removing intermediate container eea55bb99b7b
Step 9/9 : CMD ./main
---> Running in d56440eeec03
---> 31e314cff9eb
Removing intermediate container d56440eeec03
Successfully built 31e314cff9eb
Successfully tagged ref-back-go:latest

When everything is succeed, start your container with command docker run --rm -d -p 8080:8080 'your-image-name' and this will start container in background. To start container in not detached mode, just remove -d flag.

This way of building docker images with Go applications i use in my projects and it’s really fast to build on local machine, or on dockerhub, so i hope you find this article helpful too :)

Thank you for reading, any advice or critique are welcome!