Build Your Docker Image

Create a Dockerfile with this code:

DeployLocally/Dockerfile
 FROM golang:1.14-alpine AS build
 WORKDIR /go/src/proglog
 COPY . .
 RUN CGO_ENABLED=0 go build -o /go/bin/proglog ./cmd/proglog
 
 FROM scratch
 COPY --from=build /go/bin/proglog /bin/proglog
 ENTRYPOINT ["/bin/proglog"]

Our Dockerfile uses multistage builds: one stage builds our service and one stage runs it. This makes our Dockerfile easy to read and maintain while keeping our build efficient and the image small.

The build stage uses the golang:1.14-alpine image because we need the Go compiler, our dependencies, and perhaps various system libraries. These take up disk space, and we don’t need them after we have compiled our binary. In the second stage, we use the scratch empty image—the smallest Docker image. We copy our binary into this image, and this is the image we deploy.

You must statically compile your binaries for them to run in the scratch image because it doesn’t contain the system libraries needed to run dynamically linked binaries. That’s why we disable Cgo—the compiler links it dynamically. Using the scratch image helps with thinking of the containers as being immutable. Instead of exec’ing into a container and mutating the image by installing tools or changing the filesystem, you run a short-lived container that has the tool you need.

The next step is to add a target to your Makefile to build the Docker image by adding this snippet to the bottom of the file:

DeployLocally/Makefile
 TAG ?= 0.0.1
 
 build-docker:
  docker build -t github.com/travisjeffery/proglog:$(TAG) .

Then build the image and load it into your Kind cluster by running:

 $ make build-docker
 $ kind load docker-image github.com/travisjeffery/proglog:0.0.1

Now that we have our Docker image, let’s look at how we can configure and run a cluster of our service in Kubernetes with Helm.