Docker
Cheat-sheet for day-to-day and incident work — images, containers, volumes, networks, compose, and cleanup.
Images
Build, tag, transfer, and remove images.
Build
Build from Dockerfile in current dir
docker build -t myapp:1.0 . Custom Dockerfile path
docker build -f docker/Dockerfile -t myapp:1.0 . Skip layer cache
docker build --no-cache -t myapp:1.0 . Stop at an intermediate stage
docker build --target builder -t myapp:builder . Pass build args
docker build --build-arg VERSION=1.0.3 -t myapp . Multi-platform build + push (buildx)
docker buildx build --platform linux/amd64,linux/arm64 --push -t registry.example.com/myapp:1.0 . Registry
Login
docker login registry.example.com Pull
docker pull nginx:1.25-alpine Re-tag for a registry
docker tag myapp:1.0 registry.example.com/myapp:1.0 Push
docker push registry.example.com/myapp:1.0 Save / Load
Transfer full images (layers, history, ENV, CMD, ENTRYPOINT) — ideal for air-gapped environments.
Save image to tar
docker save -o myapp.tar myapp:1.0 Save + compress
docker save myapp:1.0 | gzip > myapp.tar.gz Load from tar
docker load -i myapp.tar Load from compressed tar
gunzip -c myapp.tar.gz | docker load Export / Import
Flattens a container's filesystem into a single-layer image — loses history and metadata (ENV, CMD, ENTRYPOINT). Use save/load instead when you need a faithful copy.
Export container filesystem
docker export <container> -o fs.tar Import as image
docker import fs.tar myapp:flat Inspect & Remove
List images
docker image ls Build history / layer sizes
docker history myapp:1.0 Full metadata
docker image inspect myapp:1.0 Remove image
docker rmi myapp:1.0 Prune dangling images
docker image prune Prune ALL unused images
docker image prune -a Containers
Run, inspect, and manage container lifecycles.
Run
Detached, named, port-mapped
docker run -d --name web -p 8080:80 nginx Interactive shell, auto-remove on exit
docker run -it --rm ubuntu bash Bind-mount current dir as workdir
docker run -v "$(pwd):/app" -w /app node:20 npm test Load env from file
docker run --env-file .env -d myapp Auto-restart unless manually stopped
docker run --restart unless-stopped -d myapp Resource limits
docker run --memory 512m --cpus 1.5 myapp Attach to a specific network
docker run --network my-net --name api myapp Run as non-root user
docker run --user 1000:1000 myapp Lifecycle
Start / stop / restart
docker start|stop|restart <id> Force-kill (SIGKILL)
docker kill <id> Pause / unpause (freeze processes)
docker pause <id> # docker unpause <id> Rename
docker rename old-name new-name Snapshot container to image
docker commit <id> myapp:snapshot Remove stopped container
docker rm <id> Force-remove running container
docker rm -f <id> Prune stopped containers
docker container prune Inspect & Observe
Running containers
docker ps All (including stopped)
docker ps -a Filter by status + name
docker ps -a --filter "status=exited" --filter "name=web" Follow logs, last 100 lines
docker logs -f --tail 100 <id> Full inspect (JSON)
docker inspect <id> Single field via Go template
docker inspect --format '{{.State.Status}}' <id> Live resource usage
docker stats Processes inside container
docker top <id> Daemon event stream
docker events --since 10m Exec & Copy
Shell into a running container
docker exec -it <id> sh Shell as root
docker exec -u 0 -it <id> sh Run one-off command
docker exec <id> printenv Copy file INTO container
docker cp ./file.conf <id>:/etc/app/file.conf Copy file OUT of container
docker cp <id>:/var/log/app.log ./app.log Volumes & Mounts
Persistent storage for containers.
Named volumes
Create
docker volume create mydata List
docker volume ls Inspect (see mountpoint on host)
docker volume inspect mydata Remove
docker volume rm mydata Prune unused
docker volume prune Mount syntax
In -v, a leading "/" means bind-mount (host path); no leading "/" means named volume.
Named volume
docker run -v mydata:/data myapp Bind mount (absolute path required)
docker run -v "$(pwd):/app" myapp Read-only bind mount
docker run -v "$(pwd):/app:ro" myapp In-memory tmpfs
docker run --tmpfs /tmp:size=64m myapp Verbose --mount form
docker run --mount type=bind,source="$(pwd)",target=/app,readonly myapp Networks
Isolate and connect containers.
CRUD
List
docker network ls Create bridge network
docker network create --driver bridge my-net Custom subnet
docker network create --subnet 172.20.0.0/16 my-net Inspect (shows attached containers)
docker network inspect my-net Remove
docker network rm my-net Prune unused
docker network prune Attach / Detach
Connect a running container
docker network connect my-net web Disconnect
docker network disconnect my-net web Drivers
bridge (default, isolated virtual L2), host (share host stack, no port mapping), none (no networking), overlay (multi-host, requires swarm). Containers on the same user-defined bridge can resolve each other by name via embedded DNS.
Compose
Multi-container stacks via docker-compose.yml (Compose V2 syntax).
Lifecycle
Start in background
docker compose up -d Rebuild images first
docker compose up -d --build Stop + remove containers & networks
docker compose down Also remove named volumes
docker compose down -v Stop without removing
docker compose stop Restart a single service
docker compose restart web Scale & Profiles
Scale a service
docker compose up -d --scale worker=3 Gate services behind a profile
docker compose --profile dev up -d Observe & Exec
Status
docker compose ps Follow logs for one service
docker compose logs -f web Shell into running service
docker compose exec web sh One-off disposable container
docker compose run --rm web npm test Build & Config
Build all services
docker compose build Build without cache
docker compose build --no-cache Pull latest images
docker compose pull Validate + print merged config
docker compose config Layer compose files (override base)
docker compose -f compose.yml -f compose.prod.yml up -d Custom env file
docker compose --env-file .env.prod up -d System & Cleanup
Inspect the daemon and reclaim disk.
Info
Daemon info
docker info Disk usage breakdown
docker system df Verbose disk usage (per-image)
docker system df -v Live daemon events
docker system events Safe prune
Removes stopped containers, unused networks, and dangling images. Does NOT remove volumes.
Default prune
docker system prune Include volumes
docker system prune --volumes Aggressive prune
Full reset of unused Docker resources — verify first.
All unused images + stopped containers + networks + volumes
docker system prune -a --volumes Targeted prune
Stopped containers
docker container prune Dangling images
docker image prune All unused images
docker image prune -a Unused volumes
docker volume prune Unused networks
docker network prune Inspect before deleting
docker ps -a docker volume ls docker image ls docker system df -v Tips & Pitfalls
Hard-won defaults and things that bite in production.
Volumes hold persistent data
Databases, uploads, and caches live in volumes. docker system prune --volumes is destructive — verify with docker volume ls first.
Can't delete? It's attached
If a volume, network, or image refuses to remove, something still references it. Trace with docker ps -a --filter volume= or docker inspect.
Layer cache order matters
Copy lockfiles before source: COPY package*.json ./ → RUN npm ci → COPY . .. Source edits then reuse the cached deps layer.
Multi-stage builds shrink images
FROM node:20 AS build → compile → FROM nginx:alpine → COPY --from=build /app/dist /usr/share/nginx/html. Toolchain stays out of the runtime image.
Use a .dockerignore
Keeps .git, node_modules, .env, and tests out of the build context — faster builds and no accidental secrets in images.
Non-root + pinned tags
USER app in the Dockerfile and pin tags (node:20.11.1-alpine, not :latest) for reproducibility and defense in depth.
ARG vs ENV
ARG is build-time only and does not persist. ENV persists in the final image — never put secrets there. Use BuildKit --secret or runtime --env-file.
HEALTHCHECK for orchestrators
HEALTHCHECK CMD curl -fsS http://localhost:8080/health || exit 1 lets Swarm/Kubernetes/Compose detect unhealthy containers.
Bound log driver
Default json-file driver grows unbounded. Cap per-container: --log-opt max-size=10m --log-opt max-file=3, or set defaults in /etc/docker/daemon.json.
save/load ≠ export/import
save/load transfer full images (layers + history + metadata). export/import flatten the filesystem into one layer and drop ENV/CMD/ENTRYPOINT — not a faithful copy.