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...
For further actions, you may consider blocking this person and/or reporting abuse
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.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/etc/ssl/certs
isn't necessary when you build the production container image. It can be mounted when you run the container in production.sure, but why? I'm trying to understand why will I mount it when it's running on kubernetes?
It's a trade-off between fewer dependency on the host (by including
ca-certificates
in the image) and smaller image size (by excludingca-certificates
in the image).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.
Hey, thanks for the feedback.
ENV CGO_ENABLED 0
is already defined in theDockerfile
forbuilder
stage. I copygo.mod
andgo.sum
separately for caching. I includedca-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 productionYeah, 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.
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
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.
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 youI'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.
Hey, “make dev” is recommended for development as it uses docker compose and mounts a volume which is faster than rebuilding with “make run”
Another good alternative for live reload: github.com/cosmtrek/air
Why would you use docker? The go binary is sufficient, not? What is the added value of docker when using a go program?
when in production, I use docker to containerize my go apps to limit the app resources & auto-start the apps