67. Running Go in containers and Kubernetes
67.1 Container image basics
FROM golang:1.22 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -o /app ./cmd/server
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]
scratch is smallest; distroless is often more convenient because it
includes useful basics such as CA certificates and a non-root user variant.
For cgo-heavy apps, use a runtime image that contains the required shared
libraries.
67.2 Kubernetes probes and graceful shutdown
readinessProbe:
httpGet:
path: /readyz
port: 8080
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
terminationGracePeriodSeconds: 30
Your Go process should handle SIGTERM, stop accepting new work, let
in-flight requests finish up to a deadline, and then exit. Kubernetes will
send SIGKILL after terminationGracePeriodSeconds.
67.3 Resource limits and Go runtime settings
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"
env:
- name: GOMEMLIMIT
value: "450MiB"
Set GOMEMLIMIT below the container memory limit so the runtime starts
working harder before the kernel OOM-kills the process. Leave room for
non-Go memory: stacks, mmap, cgo, kernel buffers, and the process itself.
67.4 Configuration and secrets
Use environment variables, mounted files, or a secret manager. Avoid baking environment-specific config into the binary or image.
type Config struct {
Addr string
DatabaseURL string
LogLevel string
}
func LoadConfig() Config {
return Config{
Addr: getenv("ADDR", ":8080"),
DatabaseURL: os.Getenv("DATABASE_URL"),
LogLevel: getenv("LOG_LEVEL", "info"),
}
}
Validate config at startup. A service should fail fast if required config is missing; partial startup with broken dependencies creates harder incidents.
67.5 Deployment checklist
- Runs as non-root.
- Handles SIGTERM gracefully.
- Has readiness and liveness endpoints.
- Uses explicit HTTP server timeouts.
- Sets memory limits and, where useful,
GOMEMLIMIT. - Exposes structured logs, metrics, and traces.
- Does not log secrets.
- Has pprof available only on an internal/admin path.
- Includes build version/commit in logs and
/version. - Has rollback instructions.
That's the full arc — from go build's hello-world loop in Part I to a
capstone database engine, production-shippable service, and professional
debugging/refactoring/operations workflow in Part VIII. What follows is
reference material, not more reading: idioms, pitfalls, a glossary, and
cheat sheets to check back against while you're actually writing Go. For
structured day-by-day practice on top of this guide's theory, see the
companion golang-90-day-plan.md.
Applied in the series: Linux guide, Chapters 74–76 (PID 1 and zombies, GOMAXPROCS, GOMEMLIMIT) and the TCP/IP guide's Kubernetes networking chapter (ndots:5, the conntrack DNS race).