CodeBlanks Logo Icon CodeBlanks

Docker and deployment

Add a Dockerfile and multi-stage build.

Docker and deployment

The service is packaged with a multi-stage Docker image: the first stage builds, the second carries only the binary.

FROM golang:1.23 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server

FROM gcr.io/distroless/static
COPY --from=build /app /app
EXPOSE 8080
ENTRYPOINT ["/app"]

The result is a secure image of a few MB with no shell.

Configuration and health check

A service in a container reads its settings from environment variables and exposes a health endpoint so the orchestrator (Kubernetes, Docker) can check it:

port := os.Getenv("PORT")
if port == "" {
    port = "8080"
}
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("ok"))
})

On SIGTERM, finishing in-flight requests with srv.Shutdown(ctx) before exiting (graceful shutdown) is a good habit.

Practice Port setting

Write port(env func(string) string) string: if env("PORT") is empty, return "8080". Instead of os.Getenv, try two cases with fake functions: an empty environment and one returning "9000". Print both results on one line.

Starter code

main.go
package main

import "fmt"

func main() {
    // buraya yaz
}

Sample solution

main.go
package main

import "fmt"

func port(env func(string) string) string {
    if p := env("PORT"); p != "" {
        return p
    }
    return "8080"
}

func main() {
    bos := func(string) string { return "" }
    dolu := func(string) string { return "9000" }
    fmt.Println(port(bos), port(dolu))
}

Expected output

8080 9000

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why are <code>go.mod</code> and <code>go.sum</code> copied before the source code?

  • Because Docker requires it
  • To make the image smaller
  • To run tests
  • So the dependency layer stays cached and isn't re-downloaded when code changes Correct answer

Explanation: Docker caches layers; as long as go.mod doesn't change, the go mod download layer doesn't rerun.

2 Copy from the earlier stage

Question
FROM gcr.io/distroless/static
COPY ____ /app /app
Answer
FROM gcr.io/distroless/static
COPY --from=build /app /app

Explanation: COPY --from=build copies from the file system of the stage named build.

3 Deployment parts

Term Meaning
AS build Build stage
distroless Small shell-less base
PORT Setting from environment
/healthz Health check

All lessons in Advanced