DEV Community

The AI producer
The AI producer

Posted on

The Only 30 Docker Commands You Actually Need — A Reference I Wish I Had on Day One

I've used Docker every working day for years, and here's the honest truth: most developers learn maybe five commands (run, build, ps, logs, exec) and then never go deeper. That's like owning a Swiss army knife and only ever using the bottle opener.

After debugging enough "works on my machine" fires, slow CI builds, and mystery "no space left on device" errors, I settled on a set of about 30 patterns that cover 95% of real daily work. Below is the cheat sheet I wish someone had handed me on day one — grouped by what you're actually trying to do, not alphabetically.

Daily flow (the ones you run 50 times a day)

docker ps              # running containers only
docker ps -a           # ALL containers, including stopped (the one you actually want)
docker images          # local images
docker pull nginx      # fetch without running
Enter fullscreen mode Exit fullscreen mode

The single most useful flag nobody memorizes early:

docker run --rm -it alpine sh
# --rm   = auto-delete the container when it exits (no clutter)
# -it    = interactive + tty, so you get a real shell
Enter fullscreen mode Exit fullscreen mode

Spin up a real service with everything attached:

docker run -d --name web \
  -p 8080:80 \
  -v "$PWD/html:/usr/share/nginx/html:ro" \
  -e NGINX_HOST=example.com \
  --restart unless-stopped \
  nginx:alpine
Enter fullscreen mode Exit fullscreen mode

Read that right to left: image, restart policy, env var, bind-mounted volume (read-only), port mapping, detached, name. Once this line is muscle memory, you stop reaching for docker-compose for trivial things.

Build & image management

docker build -t myapp:1.0 .          # tag while building
docker build -t myapp --target deps . # build only one stage of a multi-stage Dockerfile
docker image prune -a                 # remove ALL unused images (frees serious disk)
docker system df                      # how much space Docker is eating
Enter fullscreen mode Exit fullscreen mode

Two things that pay back forever:

1. Always have a .dockerignore. Without it, docker build ships your node_modules, .git, and .env into the build context. Builds get slow, layers get huge, secrets leak.

node_modules
.git
.env
*.log
dist
Enter fullscreen mode Exit fullscreen mode

2. Use multi-stage builds. Build in a fat image, copy only the artifact into a slim runtime image. A Node app can drop from 1.2GB to 150MB.

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

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode

Debugging (when something is broken at 2am)

docker logs -f --tail 100 web      # follow last 100 lines
docker exec -it web sh             # shell into a running container
docker exec -it web sh             # alpine has no bash — use sh
docker inspect web                 # full config: IP, mounts, env, entrypoint
docker stats                       # live CPU/mem/net per container (like htop)
docker top web                     # processes inside the container
Enter fullscreen mode Exit fullscreen mode

The debugging combo I use most: docker inspect --format to pull one field without drowning in JSON:

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
Enter fullscreen mode Exit fullscreen mode

Networks & volumes (the "why can't they talk?" problems)

docker network create mynet
docker network ls
docker run -d --name api --network mynet myapi      # no -p needed inside the net
docker run -d --name web --network mynet nginx
Enter fullscreen mode Exit fullscreen mode

Containers on the same user-defined network resolve each other by container name. So from web you can curl http://api:3000. This is the part that makes people stop hand-managing IPs.

For data:

docker volume create pgdata                # named volume (managed by Docker)
docker run -d -v pgdata:/var/lib/postgresql/data postgres
docker volume ls
docker volume rm pgdata
Enter fullscreen mode Exit fullscreen mode

Rule of thumb: named volumes for databases (Docker manages them, survives down), bind mounts (-v $PWD:/app) for source code you're editing live.

Compose (when docker run gets too long)

docker compose up -d          # build + start everything in compose.yaml
docker compose down -v        # stop AND delete volumes (the -v is the dangerous one)
docker compose logs -f api    # one service's logs
docker compose exec db psql   # run a command in a service
docker compose build --no-cache api
Enter fullscreen mode Exit fullscreen mode

A starter compose.yaml that's worth memorizing:

services:
  web:
    build: .
    ports: ["8080:3000"]
    environment:
      DATABASE_URL: postgres://app:secret@db:5432/app
    depends_on: [db]
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
    volumes: ["pgdata:/var/lib/postgresql/data"]
volumes:
  pgdata:
Enter fullscreen mode Exit fullscreen mode

docker compose up -d and you have a full stack. docker compose down -v tears it all down including data — perfect for a clean local reset.

Advanced / cleanup (the ones that save your disk)

docker system prune -a --volumes   # nuclear: everything not currently in use
docker tag myapp:1.0 me/myapp:latest
docker push me/myapp:latest
docker save myapp:1.0 | gzip > app.tar.gz   # export image for offline/airgapped transfer
docker load < app.tar.gz
docker context use remote            # run docker CLI against a remote daemon
Enter fullscreen mode Exit fullscreen mode

And the one that makes builds 10x faster on CI — BuildKit cache mounts:

# syntax=docker/dockerfile:1
RUN --mount=type=cache,target=/root/.npm \
    npm ci
Enter fullscreen mode Exit fullscreen mode

The npm cache survives between builds instead of being thrown away every layer. Pip, apt, and cargo all benefit from the same trick.


The 80/20

If you only remember five things:

  1. docker run --rm -it for throwaway shells.
  2. .dockerignore + multi-stage builds keep images tiny.
  3. docker exec -it <c> sh to get inside a sick container.
  4. User-defined networks let containers talk by name.
  5. docker system df then docker system prune -a when the disk fills up.

Docker's CLI has ~60 commands, but these 30 patterns are what actually get typed in a real workday. Once they're reflexive, you stop fighting containers and start using them as the disposable, reproducible environments they're meant to be.


If you found this useful, I put together a printable version with all **50 commands* plus a quick-reference PDF, common failure modes, and copy-paste snippets for databases, queues, and reverse proxies: The Complete Docker Command Reference.*

What's the one Docker command or flag you wish you'd learned earlier? I'm always collecting these.

Top comments (0)