To reduce docker container size we can built the image from scratch instead of using bloated images, like debian or worse ubuntu.

But to put a golang binary in it you have to take care of some important stuff. We’ll see briefly how to do it. For more details, see Building Minimal Docker Containers For Go Applications

Compile staticaly your go program :

CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -installsuffix cgo -o server

Your Dockerfile looks like this :

FROM scratch
ADD static /static
ADD server /server
CMD /server

But if you add some upload code in your program, this won’t work. The upload needs the tmp folder for big files that are sent in multipart form.
Below, the code in the os.file_unix Go package :

// TempDir returns the default directory to use for temporary files.
func TempDir() string {
  dir := Getenv("TMPDIR")
	if dir == "" {
		if runtime.GOOS == "android" {
			dir = "/data/local/tmp"
		} else {
			dir = "/tmp"
		}
	}
	return dir
}

So, as we are on linux, dir = “/tmp” is our usual suspect.

But the scratch docker does not contain a tmp folder. This was a hard bug to catch but so easy to fix, just changing the Docker file :

FROM scratch
VOLUME /tmp
ADD static /static
ADD server /server

Now link the container /tmp to the host tmp :

docker run -P -v /tmp:/tmp your_image 

That’s it ! Enjoy a fully functionnal minimal docker golang application !