Minimize GO Resource Size With Docker Multi-Stage Build
Lately, I’ve been exploring Golang. Given my Backend experience is largely in NodeJS, I anticipated a sharp learning curve. But so far, there hasn’t been as much hair pulling as I expected. GO walks a good balance between enforcing strict patterns, rules, and types while maintaining syntax conciseness and code efficiency.
Since GO is a compiled language and runs as an executable, we can take advantage of a feature from Docker 17, multi-stage build. This feature allows developers to use one base image as the builder and a more efficient or smaller one as the final resource’s image. Essentially, multi-stage lets you use the artifact from one stage in another stage.
The main benefit of this is a smaller image to deploy. It could also enable a shorter build time in the development lifecycle too because you can choose the minimal resource required.
Let’s see how:
In my example, I will create one Dockefile
that contains most of the configuration and two docker-compose
files to illustrate how to support multiple build environments, which any real-world service should have.
Docker Compose
Supporting multiple deployment environments is a pretty typical real-world requirement. Of course, you don’t see docker-compose to do this. But I’ve always preferred docker-compose for a more streamlined setup and less of a need to string up variables in docker build commands.
For my example, I created two docker-compose files with the key difference being the environment variable, ENV. This variable can be used to define which environment file the GO program will use.
For development:
docker-compose-dev.yml
version: '3.5'
services:
go-server:
build:
args:
- ENV=dev
context: .
image: go-server-dev
container_name: go-server-box-dev
ports:
- "9000:9000"
For production:
docker-compose.yml
version: '3.5'
services:
go-server:
build:
args:
- ENV=prod
context: .
image: go-server
container_name: go-server-box
ports:
- "4445:9000"