Cheat Sheets

Three dense quick references by persona—docker run and Compose for developers, BuildKit and CI/CD for DevOps, and kernel primitives plus runtime choices for architects. Use Copy sheet for plain text, persona filters to focus one role, or print (Cmd/Ctrl+P).

developer devops architect Compose V2 BuildKit

Developer Cheat Sheet

Run flags, Compose, Dockerfile instructions, debugging. Chapters: Containers, Compose, Images.

developer

docker run flags

Flag Purpose Example Notes
-d Detached (background) docker run -d nginx Returns container ID
--name Human-readable name --name web Must be unique on host
-p / -P Publish ports -p 8080:80 -P publishes all EXPOSE ports
-v / --mount Volume or bind mount -v mydata:/data Prefer --mount for explicit syntax
-e / --env-file Environment variables -e NODE_ENV=dev Visible in docker inspect
--rm Auto-remove on exit docker run --rm -it alpine sh Great for one-off commands
-it Interactive TTY docker run -it ubuntu bash Needed for shells and REPLs
--network Attach to network --network mynet host, none, bridge, custom
--restart Restart policy --restart unless-stopped no, on-failure, always
--memory / --cpus Resource limits --memory 512m --cpus 1.5 Maps to cgroup v2 limits
--user Run as UID:GID --user 1001:1001 Override image USER
--entrypoint Override ENTRYPOINT --entrypoint sh CMD becomes args to entrypoint
--health-cmd Runtime healthcheck --health-cmd "curl -f localhost/health" Overrides Dockerfile HEALTHCHECK
--add-host Extra /etc/hosts entry --add-host api.local:127.0.0.1 Dev-only host aliases
# Typical local dev container
docker run -d --name api \
  -p 8080:8080 \
  -v "$(pwd)":/app:ro \
  -e SPRING_PROFILES_ACTIVE=dev \
  --restart unless-stopped \
  myregistry/api:dev

Docker Compose commands

CommandPurposeNotes
docker compose upStart services-d detached; --build rebuild images
docker compose downStop and remove-v removes named volumes
docker compose psList containers-a includes stopped
docker compose logsService logs-f follow; --tail=100
docker compose execRun in running serviceexec api sh — no new container
docker compose runOne-off task containerOverrides command; useful for migrations
docker compose buildBuild images--no-cache, --pull
docker compose pullPull service imagesCI/CD deploy prep
docker compose configValidate & render YAMLCatches merge errors early
docker compose watchSync + rebuild on changeCompose 2.22+ dev workflow
docker compose --profileEnable profiled services--profile debug up
COMPOSE_FILE / -fMulti-file merge-f compose.yml -f compose.prod.yml
# compose.yaml essentials
services:
  api:
    build: .
    ports: ["8080:8080"]
    environment:
      DATABASE_URL: postgres://db:5432/app
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 10s
      retries: 3
  db:
    image: postgres:16-alpine
    volumes: [pgdata:/var/lib/postgresql/data]

volumes:
  pgdata:

Dockerfile instructions (quick ref)

InstructionWhenExamplePitfall
FROMBase image; new stageFROM node:22-alpine@sha256:…:latest breaks reproducibility
RUNBuild command → layerRUN npm ci && npm run buildChain with &&; each RUN = layer
COPYCopy from contextCOPY --chown=app:app . .Order matters for cache
WORKDIRSet cwdWORKDIR /appAbsolute paths only
ENVRuntime env varENV NODE_ENV=productionVisible at runtime
ARGBuild-time onlyARG VERSION=1.0In docker history — no secrets
EXPOSEDocument portEXPOSE 8080Does not publish to host
ENTRYPOINTMain process (PID 1)ENTRYPOINT ["java","-jar","app.jar"]Exec form preferred
CMDDefault argsCMD ["--spring.profiles.active=prod"]Overridden by docker run …
USERNon-root runtimeUSER 1001Create user in earlier RUN
HEALTHCHECKContainer probeHEALTHCHECK CMD curl -f localhost/healthRequired for orchestration

Debugging commands

CommandPurpose
docker logs -f --tail 200 <name>Stream recent logs
docker logs --since 5m <name>Logs since timestamp
docker exec -it <name> shShell into running container
docker exec -u root <name> apk add curlDebug as root (dev only)
docker inspect <name>Full JSON state/config
docker inspect --format '{{.State.ExitCode}}' <name>Go-template field extract
docker statsLive CPU/mem/net I/O
docker top <name>Processes inside container
docker eventsStream daemon events
docker diff <name>Filesystem changes vs image
docker cp <name>:/path ./localCopy files out for inspection
# Why did it exit?
docker inspect --format '{{.State.Status}} exit={{.State.ExitCode}} oom={{.State.OOMKilled}}' myapp

# Which IP on the bridge network?
docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' myapp

# Follow logs with timestamps
docker logs -f --timestamps myapp 2>&1 | grep -i error

Volume & port syntax

TypeSyntaxExampleUse when
Named volume -v <name>:<path> -v pgdata:/var/lib/postgresql/data DB persistence; Docker manages storage
Bind mount -v <host>:<path> -v $(pwd)/src:/app/src Hot reload; dev source sync
Read-only bind -v <host>:<path>:ro -v ./config:/etc/app:ro Config injection without writes
Anonymous volume -v <path> -v /tmp/cache Ephemeral writable layer override
Mount (explicit) --mount type=… --mount type=volume,source=pgdata,target=/data Production clarity; required options
Port publish -p host:container -p 127.0.0.1:8080:80 Bind to localhost only in dev
UDP port -p host:container/udp -p 5353:5353/udp DNS/mDNS services
Port range -p start-end:start-end -p 8000-8010:8000-8010 Multiple adjacent ports
# --mount examples (preferred in prod docs)
docker run --mount type=bind,source=/opt/data,target=/data,readonly nginx
docker run --mount type=volume,source=logs,target=/var/log/myapp nginx
docker run --mount type=tmpfs,target=/run,tmpfs-size=64m nginx

# Compose volume shorthand
volumes:
  - ./src:/app/src:cached    # macOS bind performance hint
  - config:/etc/myapp:ro

DevOps Cheat Sheet

Multi-stage builds, BuildKit, registry ops, CI/CD, linting, scanning. Chapters: Dockerfile Patterns, Registry, CI/CD.

devops

Multi-stage patterns

PatternStagesRuntime base
Java / Spring BootMaven/Gradle builder → JREeclipse-temurin:21-jre-alpine or distroless
Node.jsnpm ci && build → slim runtimenode:22-alpine; copy node_modules prod only
Pythonvenv/poetry build → slimpython:3.12-slim; multi-stage pip install
GoCompile static binaryFROM scratch or distroless/static
Frontend + Nginxnpm build → nginx servenginx:alpine; copy dist/ only
Layered JAR (Spring)Extract layers in builderSeparate COPY for deps vs app code
# syntax=docker/dockerfile:1
FROM golang:1.22 AS builder
WORKDIR /src
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app .

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

BuildKit mount types

Mount typePurposeDockerfile / CLINotes
type=cache Persist package manager caches RUN --mount=type=cache,target=/root/.m2 … Speeds rebuilds; not in final image
type=secret Build-time credentials RUN --mount=type=secret,id=npm_token … docker build --secret id=npm_token,src=…
type=ssh SSH agent for private repos RUN --mount=type=ssh git clone … docker build --ssh default
type=bind Bind host path into build RUN --mount=type=bind,from=builder,src=/out … Cross-stage artifact copy alternative
type=tmpfs Ephemeral writable dir RUN --mount=type=tmpfs,target=/tmp … No layer bloat from temp files
# Enable BuildKit
export DOCKER_BUILDKIT=1

# buildx with registry cache (CI)
docker buildx build \
  --cache-from type=registry,ref=myregistry/myapp:buildcache \
  --cache-to type=registry,ref=myregistry/myapp:buildcache,mode=max \
  --platform linux/amd64,linux/arm64 \
  --push -t myregistry/myapp:$(git rev-parse --short HEAD) .

Registry commands

CommandPurpose
docker login myregistry.ioAuthenticate (stores in config.json)
docker tag src:tag myregistry.io/ns/img:tagRetag for push target
docker push myregistry.io/ns/img:tagUpload image layers
docker pull myregistry.io/ns/img@sha256:…Pull by immutable digest
docker manifest inspect img:tagMulti-arch manifest list
docker buildx imagetools inspect img:tagRegistry-side manifest inspect
docker buildx imagetools create -t img:1.2 a:sha… b:sha…Create multi-arch manifest
crane copy src:tag dst:tagCopy between registries (no local pull)
cosign sign myregistry.io/ns/img@sha256:…Sign image digest
cosign verify --certificate-identity-regexp …Verify signature in deploy

Tagging strategy

TagMutable?When to useDeploy rule
sha-<git> / <pipeline-id>NoEvery CI buildImmutable artifact ID
v1.2.3 (semver)Yes (re-tag risk)Release promotionPin digest in prod manifests
main / developYesBranch head trackingNever deploy to prod directly
latestYesConvenience onlyAvoid in production
2026.06.05 (date)YesScheduled releasesCombine with git SHA tag
# Promotion flow (dev → staging → prod)
# CI pushes:  myapp:sha-a1b2c3d  +  myapp:main
# Staging deploys digest of sha-a1b2c3d
# Prod promotion retags or updates manifest to same digest — never rebuild

CI/CD pipeline steps

StepTool / commandGate
1. Lint Dockerfilehadolint DockerfileFail on DL3xxx errors
2. Build imagedocker buildx build / KanikoBuildKit cache hit > 70%
3. Scan imageTrivy / Docker ScoutBlock CRITICAL unfixed CVEs
4. Generate SBOM--attest type=sbom / SyftAttach to registry artifact
5. Sign imagecosign / NotationPolicy requires signature
6. Push tagsdocker push git SHA + semverDigest recorded in CI output
7. Deploy by digestCompose/K8s/ECS manifestNo floating :latest in prod
8. Smoke testHealthcheck / contract testRollback on failure
# GitHub Actions sketch
- run: hadolint Dockerfile
- uses: docker/build-push-action@v6
  with:
    push: true
    tags: ${{ env.REGISTRY }}/app:${{ github.sha }}
    cache-from: type=gha
    cache-to: type=gha,mode=max
- run: trivy image --exit-code 1 --severity CRITICAL ${{ env.REGISTRY }}/app:${{ github.sha }}

hadolint rules (common)

RuleMeaningFix
DL3006Always tag image versionFROM alpine:3.20 not alpine
DL3008Pin apt packagesapt-get install pkg=1.2.3
DL3013Pin pip packagespip install pkg==1.2.3
DL3018Pin apk packagesapk add pkg=1.2.3
DL3025JSON args recommendedExec form CMD ["npm","start"]
DL3059Multiple consecutive RUNMerge RUN instructions
DL4000MAINTAINER deprecatedUse LABEL
DL4001apt-get upgrade discouragedRebuild base image instead
DL4006ln without -f or -sUse proper symlink flags
SC2086Unquoted variable (shellcheck)Quote "$VAR"

Scanning — Trivy & Docker Scout

CommandPurpose
trivy image myapp:latestScan local or remote image
trivy image --severity CRITICAL,HIGH myapp:tagFilter severity
trivy image --exit-code 1 --ignore-unfixed myapp:tagCI gate (fail on fixable CVEs)
trivy fs --scanners vuln,secret .Scan repo + secrets pre-build
trivy sbom / --format spdx-json -o sbom.jsonGenerate SBOM
trivy image --format sarif -o results.sarif myappSARIF for GitHub Code Scanning
docker scout quickview myapp:tagCVE summary + base image recommendations
docker scout cves myapp:tagDetailed vulnerability list
docker scout recommendations myapp:tagSafer base image suggestions
docker scout compare --to myapp:old myapp:newDiff CVEs between tags
docker scout enrollEnable Scout for org images
# CI policy example
trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed "$IMAGE"
docker scout cves "$IMAGE" --only-severities critical,high

Platform / Architect Cheat Sheet

Kernel isolation, security posture, logging, runtime choices. Chapters: Internals, Security, Production.

architect

Linux namespaces reference

NamespaceIsolatesDocker flag / relevancePitfall
PIDProcess treeContainer init = PID 1; orphan reaping--pid=host exposes host PIDs
NETInterfaces, routes, iptablesBridge networking, -p NAT publish--network=host = no network isolation
MNTMount tableRootfs, volumes, bind mountsBind mounts can leak host paths
UTSHostname--hostnameCosmetic; DNS is separate
IPCSHM, semaphores, mqIsolates /dev/shm--ipc=host for legacy SHM apps
USERUID/GID mappingRootless Docker / PodmanBind mount ownership must match subuids
CGROUPCgroup hierarchy viewContainer sees own cgroup subtreeDelegation misconfig breaks limits
TIMEBoot/monotonic clockNiche testing scenariosRequires CAP_SYS_TIME
# Inspect namespace inodes for container PID
PID=$(docker inspect --format '{{.State.Pid}}' myapp)
ls -la /proc/$PID/ns/    # different inode = isolated from host

cgroup v2 flags & limits

Resourcedocker run flagCompose equivalentNotes
Memory max--memory 512mdeploy.resources.limits.memoryOOM kill when exceeded
Memory + swap--memory 512m --memory-swap 1g-1 = unlimited swap
Memory reservation--memory-reservation 256mreservations.memorySoft guarantee under pressure
CPU quota--cpus 2limits.cpusFractional CPUs OK
CPU shares--cpu-shares 512Relative weight under contention
CPU pinning--cpuset-cpus 0,1NUMA-sensitive workloads
PIDs max--pids-limit 200Prevents fork bombs
Block I/O--device-read-bpsThrottle disk per device
OOM behavior--oom-kill-disableDangerous; requires --privileged
# cgroup v2 path (host)
cat /sys/fs/cgroup/system.slice/docker-$(docker inspect -f '{{.Id}}' myapp).scope/memory.max

# Production defaults
--memory 1g --cpus 2 --pids-limit 500 --restart unless-stopped

Security options

OptionEffectProduction defaultRisk if misused
--read-onlyRootfs read-onlyEnable + tmpfs for /tmpApp needs writable dirs → use volumes
--cap-drop ALLDrop all capabilitiesDrop all, add minimalMissing CAP_NET_BIND_SERVICE for <1024 ports
--cap-addGrant specific capsRarely neededCAP_SYS_ADMIN ≈ root
--security-opt no-new-privilegesBlock privilege escalationAlways in prodsetuid binaries won't elevate
--security-opt seccomp=…Syscall filter profileDefault Docker profileCustom profile can break JVM/GUI
--security-opt apparmor=…MAC profile (Ubuntu)docker-defaultCustom profile maintenance
--privilegedAll caps + host devicesNever in prodFull host compromise vector
--user 1001:1001Non-root runtimeAlwaysFile permission mismatches on volumes
--userns-remapUID mapping (daemon-level)Consider for multi-tenantHost file ownership complexity
Socket mount/var/run/docker.sockNever in app containers= root on host

Image hardening checklist

#CheckVerify
1Pin base image to digestFROM img@sha256:…
2Run as non-root USERdocker inspect .Config.User
3No secrets in ENV/ARG/layersdocker history + Trivy secret scan
4Minimal runtime base (distroless/alpine)Image size & attack surface audit
5Multi-stage build; no build tools in runtimeInspect final stage layers
6HEALTHCHECK defineddocker inspect .Config.Healthcheck
7CVE scan gate in CITrivy/Scout CRITICAL = 0 unfixed
8Sign images; verify at deploycosign verify policy
9SBOM attachedRegistry attestations / Syft output
10Read-only rootfs where possible--read-only + tmpfs mounts
11Drop ALL caps; no privilegeddocker inspect .HostConfig.Privileged
12No latest tag in production deployManifest pinned to digest

Logging driver comparison

DriverStorageBest forLimitations
json-file (default) Local JSON files Dev, single-host Compose Disk fills; no central aggregation
local Local binary, auto-rotated Single-host prod without agent Still host-local only
journald systemd journal Linux hosts with journald Coupled to init system
syslog Remote syslog server Legacy SIEM integration UDP loss; TLS config needed
fluentd Fluentd/Fluent Bit forward Kubernetes + Fluent stack Buffer/backpressure tuning
awslogs CloudWatch Logs ECS/Fargate on AWS AWS-specific; IAM roles
gcplogs Google Cloud Logging GCE/GKE workloads GCP-specific
none Discarded Batch jobs with no log need No debugging trail
# daemon.json — rotate json-file logs
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "5" }
}

# Per-container override
docker run --log-driver=fluentd --log-opt fluentd-address=localhost:24224 myapp

Docker vs Podman vs containerd

DimensionDocker (rootful)Podmancontainerd
Architecture Central dockerd daemon Daemonless fork/exec per container Low-level CRI runtime (no CLI UX)
Rootless default Opt-in setup Default on many distros Via nerdctl / k8s CRI
Compose docker compose podman compose (compatible) Not native — use K8s/nerdctl compose
Kubernetes dockerd removed from nodes (1.24+) podman generate kube for migration Default node runtime via CRI
Build images docker buildx (BuildKit) podman build (Buildah backend) nerdctl build / external CI only
OCI compatibility Full — same registries Full — pull/push identical images Full — runs same OCI artifacts
Socket risk docker.sock = root on host No central socket by default containerd.sock also privileged
Best fit Developer ergonomics, local dev Rootless/RHEL/OpenShift edge K8s production runtime layer