Docker cheat sheet

A scannable Docker reference: 23 short snippets across 12 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Images and containersAn image is an ordered set of read-only layers plus a small config that says which command to run. docker pulllesson
Writing a DockerfileEvery instruction creates a layer. Docker reuses a cached layer while the instruction and its inputs are unchanged, butlesson
Compose, volumes and networkingCompose takes one YAML file and creates the whole set of containers, networks and volumes with a single command. It islesson
Installing Docker and the core CLI workflowDocker is three things wearing one name: a client (docker), a long-running daemon (dockerd) that does the work, and alesson
Container lifecycle, logs and debuggingStates and restart policies, where stdout goes, exec versus attach, inspect and exit codes, and the reflex that findslesson
Registries, tags and image distributionHow an image name is assembled, why digests are the only immutable reference, and pushing to Docker Hub, GHCR or alesson
BuildKit, cache and multi-platform imagesBuildKit is the build engine behind modern Docker. The docker driver builds inside the daemon and cannot export cachelesson
Container security: users, capabilities and secretsA container runs as root unless you say otherwise, and root inside a container is root on the host kernel — namespaceslesson
Data persistence and backup patternsVolume drivers and where data really lives, permission mismatches, database containers, and a backup you have restoredlesson
Docker in CI and publishing imagesBuilding in a pipeline, caching layers across runs, tagging with the commit, scanning for vulnerabilities and signinglesson
Production concerns: resources, health and loggingCPU and memory limits, healthchecks that mean something, log rotation, and shutting down without dropping requestslesson
Podman, containerd and the OCI ecosystemDocker popularised containers but does not define them. Three Open Container Initiative specifications do: the imagelesson

Quick snippets

Images and containers

Images are stacked layers

docker pull nginx:1.27-alpine      # a tag points at a specific digest
docker images                      # what is on disk
docker history nginx:1.27-alpine   # layer by layer
docker rmi nginx:1.27-alpine       # remove (fails if a container still uses it)

Lifecycle and cleanup

docker stop web          # SIGTERM, then SIGKILL after 10 seconds
docker kill web          # SIGKILL immediately
docker restart web
docker rm web            # only when stopped; -f forces it

docker system df         # where the disk went
docker system prune -a   # reclaim space: unused images, networks, build cache

Full lesson: Images and containers →

Writing a Dockerfile

A first Dockerfile

FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
USER node
CMD ["node", "server.js"]

Layers and the build cache

# slow: any source change reinstalls every dependency
COPY . .
RUN npm ci

# fast: dependencies stay cached until the manifest changes
COPY package*.json ./
RUN npm ci
COPY . .

Layers and the build cache

docker build -t myapp:1.0 .
docker build --no-cache -t myapp:1.0 .        # verify without stale layers
docker build --target build -t myapp:debug .  # stop at a named stage

cat > .dockerignore <<'EOF'
node_modules
.git
dist
*.log
EOF

Full lesson: Writing a Dockerfile →

Compose, volumes and networking

Describing a stack with Compose

docker compose up -d          # build if needed, then start everything
docker compose ps
docker compose logs -f api
docker compose exec api sh
docker compose down           # stop and remove containers (volumes survive)

Volumes and bind mounts

docker run -d --name db \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16-alpine

docker run --rm -it -v "$PWD:/work" -w /work node:20-alpine npm test

docker volume ls
docker volume inspect pgdata

Networking

docker network ls
docker network inspect myapp_default
docker run --rm -it --network myapp_default nicolaka/netshoot nslookup db

Full lesson: Compose, volumes and networking →

Installing Docker and the core CLI workflow

What you are actually installing

docker version            # client AND server - an error here means the daemon is down
docker info               # storage driver, cgroup version, runtimes, root dir
docker context ls         # which endpoint the CLI talks to
docker context use default

# talk to a remote or rootless daemon without touching the default
DOCKER_HOST=ssh://deploy@web docker ps

Full lesson: Installing Docker and the core CLI workflow →

Container lifecycle, logs and debugging

States and restart policies

docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'
docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.OOMKilled}}' app
docker inspect app --format '{{json .HostConfig.RestartPolicy}}'

docker stop app           # SIGTERM, then SIGKILL after the grace period
docker stop -t 30 app     # give it 30 seconds to flush
docker start app          # same configuration as the original run

Logs: where they come from

docker logs app                      # everything PID 1 ever wrote
docker logs -f --tail 100 app        # follow the last 100 lines
docker logs -t --since 30m app       # timestamps, last 30 minutes
docker logs --until 2026-09-18T09:00:00 app

docker inspect -f '{{.HostConfig.LogConfig.Type}}' app
ls -lh $(docker inspect -f '{{.LogPath}}' app)   # the file on the host

# rotate it - json-file grows without limit by default
docker run -d --log-opt max-size=10m --log-opt max-file=3 --name web nginx
# or globally, in /etc/docker/daemon.json
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }

Full lesson: Container lifecycle, logs and debugging →

Registries, tags and image distribution

Anatomy of an image name

registry.example.com/team/api:1.4.2-alpine
└────────┬──────────┘ └─┬─┘ └┬┘ └────┬─────┘
     registry host     namespace repo    tag

nginx                       -> docker.io/library/nginx:latest
ghcr.io/acme/api:sha-9f3c1  -> tag carries the commit
app@sha256:8f1c...          -> digest: immutable, exact bytes

Anatomy of an image name

docker tag app:local registry.example.com/team/app:1.4.2
docker tag app:local registry.example.com/team/app:1
docker push registry.example.com/team/app:1.4.2
docker push registry.example.com/team/app:1

# pin the exact bytes you tested
docker inspect --format='{{index .RepoDigests 0}}' registry.example.com/team/app:1.4.2
docker pull registry.example.com/team/app@sha256:8f1c9a4e...

Manifests, digests and multi-architecture tags

docker buildx imagetools inspect registry.example.com/team/app:1.4.2
docker manifest inspect alpine:3.20 | head -40

# what the tag actually points at, per platform
docker buildx imagetools inspect --raw nginx:1.27-alpine | jq '.["mediaType"]'

# force the platform you want instead of the emulated default
docker pull --platform linux/arm64 alpine:3.20
docker run --rm --platform linux/amd64 alpine:3.20 uname -m

Full lesson: Registries, tags and image distribution →

BuildKit, cache and multi-platform images

Cache mounts and cache backends

# python
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

# apt: the lists directory is reused between builds
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,target=/var/lib/apt,sharing=locked \
    apt-get update && apt-get install -y --no-install-recommends curl

# go modules
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=bind,source=go.sum,target=go.sum \
    go mod download

Cache mounts and cache backends

# reuse layers across machines and CI runs
docker buildx build \
  --cache-from type=registry,ref=registry.example.com/team/app:buildcache \
  --cache-to   type=registry,ref=registry.example.com/team/app:buildcache,mode=max \
  --tag registry.example.com/team/app:1.4.2 --push .

# GitHub Actions cache, no registry needed
docker buildx build --cache-from type=gha --cache-to type=gha,mode=max --load .

# local directories, useful on one machine
docker buildx build --cache-from type=local,src=/tmp/cache --cache-to type=local,dest=/tmp/cache .

Full lesson: BuildKit, cache and multi-platform images →

Container security: users, capabilities and secrets

Never run as root by default

FROM node:20-alpine
WORKDIR /app

COPY --chown=10001:10001 package*.json ./
RUN npm ci --omit=dev
COPY --chown=10001:10001 . .

USER 10001:10001
CMD ["node", "server.js"]

Secrets that never become layers

# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./

# the token exists only for this RUN and leaves nothing behind
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm ci --omit=dev

COPY . .
USER 10001:10001

Secrets that never become layers

docker buildx build --secret id=npmrc,src=$HOME/.npmrc -t app:1.4.2 .

# proof that nothing leaked into a layer
docker history --no-trunc app:1.4.2 | grep -i -E 'token|secret|password' || echo "no secret in layers"

# at runtime, give the process a file or an env var instead of the image
docker run --rm --env-file ./secrets.env app:1.4.2
docker run --rm -v "$PWD/secrets:/run/secrets:ro" app:1.4.2

Full lesson: Container security: users, capabilities and secrets →

Data persistence and backup patterns

Where the bytes live

docker volume create --driver local \
  --opt type=nfs --opt o=addr=10.0.0.5,rw --opt device=:/export/data shared
docker volume ls
docker volume inspect pgdata --format '{{.Mountpoint}} {{.Driver}}'

sudo ls -la /var/lib/docker/volumes/pgdata/_data   # the real path on the host
docker run --rm -v pgdata:/data alpine ls -la /data

docker volume rm pgdata            # fails while a container uses it
docker volume prune                # deletes every unused volume - read twice

Full lesson: Data persistence and backup patterns →

Docker in CI and publishing images

Tag strategy

docker buildx build --push \
  --tag ghcr.io/acme/api:sha-$GIT_SHA \
  --tag ghcr.io/acme/api:1.4.2 \
  --tag ghcr.io/acme/api:1.4 \
  --cache-from type=registry,ref=ghcr.io/acme/api:buildcache \
  --cache-to type=registry,ref=ghcr.io/acme/api:buildcache,mode=max .

# record what you shipped
docker buildx imagetools inspect ghcr.io/acme/api:1.4.2 --format '{{json .Manifest.Digest}}'

Full lesson: Docker in CI and publishing images →

Production concerns: resources, health and logging

Healthchecks

HEALTHCHECK --interval=30s --timeout=3s --start-period=20s --retries=3 \
  CMD node -e "require('http').get('http://127.0.0.1:3000/health', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"

Full lesson: Production concerns: resources, health and logging →

Podman, containerd and the OCI ecosystem

How Kubernetes consumes the same images

# on a node, the runtime is containerd and the CLI you may have is nerdctl
nerdctl --namespace k8s.io ps
nerdctl -n k8s.io images | grep api

crictl ps                  # the CRI view of the same containers
crictl pull registry.example.com/team/app:1.4.2

Full lesson: Podman, containerd and the OCI ecosystem →

FAQ

Is this Docker cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 12 lessons of the Docker course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full Docker course — it carries the worked explanations, the edge cases and the exercises behind every line here.

Git Linux Kubernetes Nginx CI / CD Bash Scripting

Last refreshed 2026-09-27.