Stackbook Logo
← Back to Tools

Docker Cheat Sheet

A task-oriented Docker command reference covering images, containers, networking, volumes, Compose, and cleanup, with the pitfalls that bite in production.

4 min read

Docker packages an application and its dependencies into an image that runs the same way on a laptop, a CI runner, or a production cluster. This cheat sheet is organised by the task you are trying to do rather than by command name, so you can jump to the problem in front of you. Use it as a daily reference, and as a map of the concepts you need before moving on to orchestrators such as Kubernetes.

Build and manage images

An image is a layered, read-only template. A Dockerfile describes how to build it.

docker build -t myapp:1.0 .                 # build from ./Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .
docker images                               # list local images
docker tag myapp:1.0 registry.example.com/team/myapp:1.0
docker push registry.example.com/team/myapp:1.0
docker pull nginx:1.27-alpine
docker history myapp:1.0                    # inspect layers and sizes

A minimal multi-stage Dockerfile keeps runtime images small:

FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY package*.json ./
RUN npm ci --omit=dev
USER node
CMD ["node", "dist/server.js"]

Run and control containers

docker run -d --name web -p 8080:80 nginx:1.27-alpine
docker run --rm -it ubuntu:24.04 bash       # throwaway interactive shell
docker run -d -e DB_URL=postgres://db/app --memory 512m --cpus 1 myapp:1.0
docker ps                                   # running containers
docker ps -a                                # include stopped ones
docker stop web && docker start web
docker restart web
docker rm -f web                            # force remove

The -p host:container flag publishes a port. The --rm flag deletes the container when it exits, which keeps your machine tidy.

Debug a misbehaving container

docker logs -f --tail 100 web               # follow recent logs
docker exec -it web sh                      # shell inside a running container
docker inspect web                          # full JSON config and state
docker stats                                # live CPU and memory
docker top web                              # processes inside
docker cp web:/etc/nginx/nginx.conf ./nginx.conf

If a container exits immediately, check docker logs first, then run it with --entrypoint sh to explore the filesystem.

Networking and volumes

Containers on the same user-defined network resolve each other by name. The default bridge network does not provide this.

docker network create backend
docker run -d --name db --network backend -e POSTGRES_PASSWORD=secret postgres:16
docker run -d --name api --network backend -p 3000:3000 myapp:1.0

docker volume create pgdata
docker run -d -v pgdata:/var/lib/postgresql/data postgres:16   # named volume
docker run --rm -v "$(pwd)":/src -w /src node:22 npm test      # bind mount

Named volumes survive container removal and are the right choice for databases. Bind mounts are convenient for development.

Docker Compose

Compose defines multi-container apps in one file.

services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      DB_URL: postgres://postgres:secret@db:5432/app
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      retries: 5
volumes:
  pgdata:
docker compose up -d --build
docker compose logs -f api
docker compose ps
docker compose down            # add -v to also delete volumes

Cleanup and common pitfalls

docker system df                            # disk usage
docker image prune -a                       # remove unused images
docker container prune
docker volume prune                         # careful: deletes unused volumes
docker system prune --volumes

Watch for these mistakes:

  • Using the latest tag in production, which makes deployments non-reproducible. Pin versions or digests.
  • Running as root. Add a USER instruction.
  • Copying secrets into image layers. Layers are permanent, so use runtime environment variables or a secrets manager.
  • Forgetting a .dockerignore, which bloats the build context with node_modules and .git.
  • Storing state inside the container filesystem, which disappears when the container is replaced.

Where Docker fits in an architecture

Docker is the packaging layer. CI builds an image once, tags it with a commit SHA, and pushes it to a registry. Every environment then pulls the identical artifact, which removes "works on my machine" drift. In production, an orchestrator such as Kubernetes schedules those containers across nodes, handles restarts, and scales replicas. Compose remains ideal for local development and integration tests.

Key takeaways

  • Organise your workflow around build, run, debug, network, and clean.
  • Use multi-stage builds, pinned tags, and non-root users for small, safe images.
  • Put persistent data in named volumes, never in the container layer.
  • Use user-defined networks or Compose so services find each other by name.
  • Build once, promote the same image through every environment.