The Go 1.11 web service Dockerfile

Goals:

  • The application executable is compiled inside a container, in order to boost reproducibility
  • The resulting image must be as small as possible
  • The application must run in a container as secure as possible: an unprivileged user in a minimal environment
  • The application must be able to make HTTPS calls
  • Line 3: the ARG keyword fetches an optional command line argument. For example: docker build --build-arg GO_VERSION=1.11.2. If not provided, the default value 1.11 is used.
  • Line 10: create the unprivileged Linux group and user that will run the executable. Running an executable as root, even inside a container, is generally not advisable, specifically unnecessary, and definitely inelegant.
  • Line 17: use the Alpine package management system to install the root certificates needed for making HTTPS calls from inside the container. If you don’t plan to run an HTTPS client, you can remove this line and line 42.
  • Line 31: compile the Go application as a static binary. Because of CGO_ENABLED=0, the executable will not depend on the system C libraries and will instead embed everything that is needed to run; only statically linked binaries can run in a scratch container.
  • Line 36: FROM scratch tells Docker to start over, using a new empty base image. The first stage, FROM golang, will be discarded. The final Docker image will only contain this stage, which doesn’t even carry an operating system.
  • COPY --from=builder fetches files from the previous image, which we have named builder on line 6.
  • Line 50: tell Docker the port the application will bind to. I usually use port 8080 for exposing HTTP.
  • Line 53: thanks to the group and user files we’ve generated and imported from the first stage, there is now an unprivileged nobody user ready to be used.
  • Line 56: the arguments to ENTRYPOINT are given as a JSON array: if instead a string had been passed, Docker would have invoked sh as a tokenizer. But since there is no sh in a scratch container, it would have resulted in an error like stat /bin/sh: no such file or directory.

Alternative Dockerfile for vendored dependencies

--

--

--

Test-driven backend engineer. Cryptography consumer. Berlin, Europe.

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Pierre Prinetti

Pierre Prinetti

Test-driven backend engineer. Cryptography consumer. Berlin, Europe.

More from Medium

gohive Kerberos error: Bad SASL negotiation status: 4

Generating JSON data from Go (Golang) structs with Go2JSON

Bulktransfer via TCP and UDP in Go — A Rabbit/Turtle Race?

Cross-compilation in Go