Irbisa · Cheatsheet
Docker & Containers
Images, layers and the build cache, multi-stage Dockerfiles for Go, scratch and distroless, Compose for local development, volumes and networking, signals and PID 1, image security, multi-arch builds
What is a container, how does it differ from a virtual machine, and what do namespaces and cgroups give it?
What is the difference between an image, a container and a registry, and what is an image layer?
# one layer per build step that changed files; ENTRYPOINT only sets config$ docker image history --format 'table {{.CreatedBy}}\t{{.Size}}' registry.example.com/api:1.4.0CREATED BY SIZEENTRYPOINT ["/api"] 0BCOPY /out/api /api # buildkit 10.7MBbazel build //common:cacerts_deb... 319kB…What do
RUN,CMDandENTRYPOINTdo in a Dockerfile, and why does the exec form["/api"]matter?# syntax=docker/dockerfile:1FROM golang:1.25 AS buildWORKDIR /srcCOPY go.mod go.sum ./# RUN: executed at build time; its file changes are saved as a layerRUN go mod download…What is the difference between
EXPOSEand-p 8080:8080, and why is a Go server listening on127.0.0.1:8080unreachable through a published port?package main import ( "log" "net/http")…What is the difference between a named volume and a bind mount, where should Postgres keep its data in Compose, and what does
docker compose down -vdelete?services: postgres: image: postgres:17-alpine environment: {POSTGRES_USER: app, POSTGRES_PASSWORD: app, POSTGRES_DB: app} volumes: # named volume: managed by Docker, survives down, removed by down -v…How do you write a production Dockerfile for a Go service, and what breaks when the binary runs on
scratch?# syntax=docker/dockerfile:1FROM golang:1.25 AS buildWORKDIR /srcCOPY go.mod go.sum ./RUN go mod download # cached until go.mod/go.sum changeCOPY . .…Find the bug: after a one-line change in a handler,
docker builddownloads every module again and recompiles the whole dependency tree.# syntax=docker/dockerfile:1FROM golang:1.25 AS buildWORKDIR /srcCOPY . .RUN go mod downloadRUN CGO_ENABLED=0 go build -o /out/api ./cmd/api FROM gcr.io/distroless/static-debian12:nonrootCOPY --from=build /out/api /apiENTRYPOINT ["/api"]What is the Docker build context, and what goes wrong when a Go repository has no
.dockerignore?# .dockerignore at the root of the build context, allowlist style:# exclude everything...*# ...then re-include only what the Go build reads!go.mod!go.sum…An image built on an Apple Silicon Mac fails on an amd64 server with
exec /api: exec format error. Why, and how do you build one image for both architectures?# syntax=docker/dockerfile:1# The build stage runs natively on the builder's own platform: no emulation.FROM --platform=$BUILDPLATFORM golang:1.25 AS buildWORKDIR /srcCOPY go.mod go.sum ./RUN go mod download…Why is deploying
:latesta bad idea, and what is the difference between an image tag and a digest?# syntax=docker/dockerfile:1# wrong: a moving tag, a different image after every Go patch or Debian update# FROM golang:1.25 AS build# right: the tag is for humans; the digest decides what is pulledFROM golang:1.25.14@sha256:699337d620559a59b4a2bb298ad59611e535d2ee755a34cf2d2a98f37578dc80 AS buildWORKDIR /src…The Alpine-based container starts via
entrypoint.sh, which reads a secret and runs/app/server. Pods now take the full 30 s to stop and never log a shutdown. Why?#!/bin/sh# entrypoint.shset -euDB_PASSWORD="$(cat /run/secrets/db-password)"export DB_PASSWORD…Why should a Go container run as a non-root user, and how do you set that up on
scratchor distroless?# Dockerfile: USER 65532:65532 (numeric, so runAsNonRoot can verify it)spec: securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532…Why must secrets never be baked into a container image, and how should a Go service get them instead, at build time and at runtime?
# syntax=docker/dockerfile:1FROM golang:1.25 AS buildWORKDIR /srcENV GOPRIVATE=github.com/acme/*COPY go.mod go.sum ./# wrong: ARG GITHUB_TOKEN, then RUN git config ... $GITHUB_TOKEN…How do you set up local development for a Go service with Postgres and Redis in Docker Compose, and how do you make the service wait until the database is ready?
services: api: build: . ports: ["8080:8080"] environment: DATABASE_URL: postgres://app:app@postgres:5432/app?sslmode=disable…Find the bug: the API reaches Postgres when started with
go run, but in Compose it exits withdial tcp 127.0.0.1:5432: connect: connection refused.services: api: build: . ports: - "8080:8080" environment: DATABASE_URL: postgres://app:app@localhost:5432/app?sslmode=disable depends_on: postgres: condition: service_healthy postgres: image: postgres:17-alpine environment: {POSTGRES_USER: app, POSTGRES_PASSWORD: app, POSTGRES_DB: app} ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U app -d app"] interval: 2sHow do you secure a Go service's container image beyond running as non-root: scanning, SBOMs, signing and runtime restrictions?
# 1. scan: OS packages plus the Go modules and stdlib recorded in the binary$ trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 \ registry.example.com/api:1.4.0 # 2. Go-aware triage: which vulnerable functions are linked into the binary# (needs symbols: scan a build made without -ldflags=-s)…The service runs on distroless, so
docker exec -it api shfails withexecutable file not found. How do you debug the running container?$ docker exec -it api shOCI runtime exec failed: exec failed: unable to start container process:exec: "sh": executable file not found in $PATH # Docker: a toolbox container in the same PID and network namespaces$ docker run --rm -it --pid=container:api --network=container:api \…What is the difference between Docker, containerd, runc and Podman, and what changed for your images when Kubernetes removed dockershim in 1.24?