Docker¶
On this page
Containers from the ground up: images vs containers, the Dockerfile, networking and volumes, Compose for multi-service apps, and the practices that keep images small and safe.
Basics¶
Docker packages an application and its dependencies into a container — an isolated, portable process that shares the host kernel. Containers use Linux namespaces (isolation) and cgroups (resource limits), so they're far lighter than VMs.
Image vs container¶
- Image — an immutable, layered template (read-only). Built from a Dockerfile.
- Container — a running (or stopped) instance of an image, with a thin writable layer on top.
- Registry — stores/distributes images (Docker Hub, GHCR, ECR, GCR, Harbor).
Architecture¶
The Docker CLI talks to the Docker daemon (dockerd), which manages images,
containers, networks, and volumes via containerd and runc (OCI runtime). Images and
the runtime follow OCI standards.
Storage & networking¶
- Volumes — Docker-managed persistent storage (
/var/lib/docker/volumes). Survive container removal. - Bind mounts — map a host path into the container.
- tmpfs — in-memory, ephemeral.
- Networks —
bridge(default, single host),host(share host net),none,overlay(multi-host/Swarm). Containers on the same user-defined bridge resolve each other by name.
Cheatsheet¶
Images & containers¶
docker build -t app:1.0 .
docker images ; docker pull nginx:alpine
docker run -d --name web -p 8080:80 nginx:alpine
docker run -it --rm ubuntu bash # interactive, auto-remove
docker ps ; docker ps -a # running / all
docker logs -f web
docker exec -it web sh # shell into a running container
docker stop web ; docker start web ; docker rm web
docker rmi nginx:alpine
docker stats # live resource usage
docker inspect web # full JSON metadata
Volumes & networks¶
docker volume create data
docker run -v data:/var/lib/mysql mysql:8
docker run -v $(pwd):/app -w /app node:20 npm test # bind mount
docker network create appnet
docker run --network appnet --name db postgres:16
Cleanup (reclaim space)¶
docker system df # what's using disk
docker container prune # remove stopped
docker image prune -a # remove unused images
docker system prune -a --volumes # nuke unused everything (careful)
Registry¶
Dockerfile (multi-stage, small & cached)¶
# 1) build stage
FROM golang:1.22 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download # cached unless deps change
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server
# 2) minimal runtime
FROM gcr.io/distroless/static
COPY --from=build /app /app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app"]
docker compose (compose.yaml)¶
services:
web:
build: .
ports: ["8080:8080"]
environment:
- DB_HOST=db
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
volumes:
- dbdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
retries: 5
volumes:
dbdata:
docker compose up -d ; docker compose logs -f ; docker compose down
docker compose down -v # also remove volumes
Thumb Rules¶
Rules of thumb
- One concern per container. A container should run one main process (PID 1).
- Containers are ephemeral. Persist anything important in volumes/databases, not the container layer.
- Order Dockerfile from least- to most-frequently-changing to maximize layer cache (deps before code).
- Pin image tags / use digests.
latestis not reproducible. - Smaller is better and safer — use
alpine/slim/distroless, multi-stage builds. - Don't run as root inside the container unless you must.
- Don't bake secrets into images. Use env/secret managers at runtime.
- Use
.dockerignoreto keep build context (and image) lean. - A container exits when PID 1 exits — keep the foreground process running.
Use Cases¶
- Consistent dev/prod parity — “works on my machine” disappears.
- Microservices — package and ship each service independently.
- CI/CD — reproducible build/test environments.
- Packaging tools/CLIs — distribute as images.
- Local stacks — spin up DB + cache + app with Compose.
- Foundation for Kubernetes — K8s schedules OCI containers.
Common Issues¶
Container exits immediately
The main process finished or crashed. Check docker logs <name>. The foreground process
must stay running; a shell with no command, or a daemon that forks, will exit.
Port not reachable
You didn't publish it (-p host:container), the app binds 127.0.0.1 instead of
0.0.0.0, or a host firewall blocks it. Verify with docker ps (PORTS column).
Data disappeared after docker rm
It lived in the writable container layer. Use a named volume or bind mount for anything that must persist.
Image is huge / build is slow
No multi-stage build, copying everything (missing .dockerignore), or cache busted by
COPY . . before installing deps. Reorder and slim the base image.
“no space left on device”
Dangling images/volumes/build cache piled up. docker system df then
docker system prune (and --volumes carefully).
Permission denied on bind mount
Host vs container UID/GID mismatch, or SELinux. Match the user, set :z/:Z on SELinux
hosts, or adjust ownership.
Networking between containers fails
On the default bridge, name resolution isn't automatic. Put them on a user-defined network so they can reach each other by service/container name.
Best Practices¶
- Multi-stage builds + minimal base images (distroless/alpine/slim).
- Run as non-root, set a read-only root FS where possible, drop capabilities.
- Pin versions/digests; rebuild regularly for security patches.
- Scan images (Trivy, Grype,
docker scout) and use trusted base images. - Externalize config & secrets (env vars, secret managers), never in the image.
- Add
HEALTHCHECKso orchestrators know real readiness. - Set resource limits (
--memory,--cpus) to protect the host. - Use
.dockerignoreand keep build context small. - One process per container; use Compose/K8s for multi-service apps.
Official Sources¶
- Docker Documentation — https://docs.docker.com/
- Dockerfile reference — https://docs.docker.com/reference/dockerfile/
- Dockerfile best practices — https://docs.docker.com/build/building/best-practices/
- Docker Compose — https://docs.docker.com/compose/
- Networking — https://docs.docker.com/engine/network/
- Storage / volumes — https://docs.docker.com/engine/storage/
- OCI specifications — https://opencontainers.org/
- Docker Scout (image analysis) — https://docs.docker.com/scout/