Docker and deployment
- Go course
- Advanced
- Lesson 46/68
- 6 min
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
package main
import "fmt"
func main() {
// buraya yaz
}Sample solution
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
FROM gcr.io/distroless/static
COPY ____ /app /app
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 |