Skip to main content

Docker cheatsheet

A one-page reference for Docker. For image layering internals and the full debugging playbook, see the complete guide.

๐Ÿ“– Full guide: Docker โ†’

Dockerfile essentialsโ€‹

FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

ENTRYPOINT vs CMDโ€‹

ENTRYPOINT ["node"]
CMD ["server.js"] # default arg โ€” overridable at `docker run`

docker run img worker.js runs node worker.js. CMD alone is fully replaced by run args; ENTRYPOINT args are appended to.

Layer-order optimizationโ€‹

COPY package*.json ./
RUN npm ci # cached unless package.json changes
COPY . . # app code changes don't invalidate deps layer

Order instructions from least โ†’ most frequently changing.

Multi-stage buildโ€‹

FROM node:20 AS build
WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM node:20-slim
COPY --from=build /app/dist /app
CMD ["node", "/app/index.js"]

Final image excludes build tools/devDependencies โ€” much smaller.

Container lifecycleโ€‹

docker run -d --name web -p 8080:80 nginx
docker ps
docker logs -f web
docker exec -it web sh
docker stop web && docker rm web

Resource limitsโ€‹

docker run --memory=512m --cpus=1.5 myapp

Exceeding --memory โ†’ OOM-killed (exit code 137), not throttled.

Volumes vs bind mountsโ€‹

docker run -v mydata:/var/lib/db postgres        # named volume (managed)
docker run -v $(pwd):/app node # bind mount (host path)
docker run --tmpfs /app/cache alpine # tmpfs (RAM, ephemeral)

Networkingโ€‹

docker network create appnet
docker run --network appnet --name db postgres
docker run --network appnet -e DB_HOST=db myapp

-p 8080:80 creates an iptables DNAT rule mapping host:container ports.

docker-composeโ€‹

services:
web:
build: .
ports: ["3000:3000"]
depends_on: [db]
db:
image: postgres:16
volumes: ["dbdata:/var/lib/postgresql/data"]
volumes:
dbdata:
docker compose up -d
docker compose logs -f web

Tagging & registriesโ€‹

docker build -t myapp:1.2.0 .
docker tag myapp:1.2.0 registry.example.com/myapp:1.2.0
docker push registry.example.com/myapp:1.2.0

Avoid :latest in production โ€” it's not pinned, breaks reproducibility.

.dockerignoreโ€‹

node_modules
.git
*.log
.env

Keeps the build context small and prevents secrets/local state from leaking into image layers.

Common pitfallsโ€‹

  • Running as root inside the container (add a non-root USER).
  • No .dockerignore โ†’ slow, bloated builds.
  • :latest tags โ†’ non-reproducible deploys.
  • One giant RUN layer โ†’ poor cache reuse; split logically instead.
See: Debugging Playbook