DEV Community

Cover image for Dockerize your Go app

Dockerize your Go app

Karan Pratap Singh on July 24, 2021

Go is quickly becoming one of my favorite languages to work with. So, today we'll dockerize our Go app by taking advantage of builder pattern and m...
Collapse
 
yoursunny profile image
Junxiao Shi

ENV CGO_ENABLED 0 is very important.
If it's forgotten, the program won't start.

Alpine and ca-certificates could be avoided if you mount /etc/ssl/certs directory from the host system.

Collapse
 
karanpratapsingh profile image
Karan Pratap Singh

Agreed! however as the production stage would be built on CI, I don't think it we would want to mount the /etc/ssl/certs host system

Collapse
 
yoursunny profile image
Junxiao Shi

/etc/ssl/certs isn't necessary when you build the production container image. It can be mounted when you run the container in production.

Thread Thread
 
karanpratapsingh profile image
Karan Pratap Singh

sure, but why? I'm trying to understand why will I mount it when it's running on kubernetes?

Thread Thread
 
yoursunny profile image
Junxiao Shi

It's a trade-off between fewer dependency on the host (by including ca-certificates in the image) and smaller image size (by excluding ca-certificates in the image).

Collapse
 
andreidascalu profile image
Andrei Dascalu

Cgo enabled to 0 is important.
I'm never quite sure why you'd need to copy the go.mod/sum separately and then still copy everything back anyway.
It's much easier to dockerignore any local build artefacts/cache and save yourself a couple of layers.
In production you only need ca-certificates if and only if you make external https calls.
Otherwise you're better off doing it from "scratch" since you also don't need a package manager at runtime.

Collapse
 
karanpratapsingh profile image
Karan Pratap Singh

Hey, thanks for the feedback. ENV CGO_ENABLED 0 is already defined in the Dockerfile for builder stage. I copy go.mod and go.sum separately for caching. I included ca-certificates as it's better to have it just in case (imo). Also I avoid from "scratch" as it's quite limiting when you're trying to debug in production

Collapse
 
andreidascalu profile image
Andrei Dascalu

Yeah, it's probably a matter of micro optimisation, caching the few bytes those files have vs having an extra layer that means an extra http call when get by the image.
But on the production build things, having things just in case is a bad practice. Just as is allowing yourself the possibility to install stuff for debug production. That's a pretty gaping security hole alongside not running your application under a limited user (alongside disabling root altogether). Containers are meant for running a single isolated process, debugging in a containerised environment should be done via a dedicated container.

Collapse
 
clavinjune profile image
Clavin June

you may use -ldflags "-s -w" on go build to make the binary smaller and use distroless container for running the binary, it makes the image result smaller too.

You can use upx to compress the binary also

Collapse
 
cctechwiz profile image
Josh Maxwell

Do you always use a docker image for running your dev build locally instead of just using 'go run'? I tried that because it seems like good practice to use the same env as prod. But it really killed my flow waiting the extra time between small changes for docker to start the image.

Collapse
 
karanpratapsingh profile image
Karan Pratap Singh

Hi Josh, yes I use docker to develop in Go. What issue are you facing? are you using docker-compose and develoment stage? for me it's pretty much instant restart. You can use normal go run if it works best for you

Collapse
 
cctechwiz profile image
Josh Maxwell

I'm not yet using the multistage build I'll give that a whirl on Monday. My main hang up is that it takes like 10-15 seconds to run my 'make run' ( which uses docker) and that little delay really builds up over the day. I'll give the multistage build a try thought. And I'm.not using docker-compise since I only have one container so far.

Thread Thread
 
karanpratapsingh profile image
Karan Pratap Singh

Hey, “make dev” is recommended for development as it uses docker compose and mounts a volume which is faster than rebuilding with “make run”

Collapse
 
narven profile image
Pedro Luz

Another good alternative for live reload: github.com/cosmtrek/air

Collapse
 
jhelberg profile image
Joost Helberg

Why would you use docker? The go binary is sufficient, not? What is the added value of docker when using a go program?

Collapse
 
clavinjune profile image
Clavin June

when in production, I use docker to containerize my go apps to limit the app resources & auto-start the apps