Skip to content

Docker basics

Core concepts and day-to-day commands.

Images vs containers

An image is a read-only snapshot — a layered filesystem plus metadata. A container is a running (or stopped) instance of an image; it adds a thin writable layer on top. The image is immutable: you can create many containers from one image simultaneously.

docker images              # list local images
docker ps                  # running containers
docker ps -a               # all containers (including stopped)

docker run flags

The flags you reach for most often:

docker run \
  -d \                          # detach (run in background)
  -p 8080:80 \                  # host_port:container_port
  -v /host/path:/app/data \     # bind-mount
  -e DATABASE_URL=postgres://…  # environment variable
  --name myapp \                # give it a name
  --restart unless-stopped \    # restart policy
  nginx:alpine

Run a one-shot command and remove the container afterwards:

docker run --rm -it python:3.12-slim python3

Volumes vs bind-mounts

Bind-mount Named volume
Location Host path you choose Docker-managed under /var/lib/docker/volumes/
Portability Tied to host path Portable across compose projects
Use for Config files, source code Database data, persistent state

Create and inspect a named volume:

docker volume create mydata
docker volume inspect mydata

Compose essentials

Start all services in the background:

docker compose up -d

Rebuild images before starting (after Dockerfile changes):

docker compose up -d --build

Tail logs for a specific service:

docker compose logs -f web

Open a shell in a running service:

docker compose exec web sh

Stop and remove containers (keeps volumes):

docker compose down

Stop, remove containers and named volumes:

docker compose down -v

Multi-stage builds

Produce a small final image by discarding build tools:

# Stage 1 — build
FROM golang:1.22 AS builder
WORKDIR /src
COPY . .
RUN go build -o /app/server ./cmd/server

# Stage 2 — runtime
FROM debian:bookworm-slim
COPY --from=builder /app/server /usr/local/bin/server
CMD ["server"]

The final image contains only the compiled binary, not the Go toolchain.

Cleaning up

Remove unused images, stopped containers, dangling build cache:

docker image prune -f       # dangling images only
docker image prune -a -f    # ALL unreferenced images (careful on shared host)
docker volume prune -f      # unnamed volumes not used by any container
docker system prune -f      # images + stopped containers + networks + cache

See also: Linux CLI recipes for find and du to audit disk usage before pruning.