docker compose up★Build, create, start & attach to all services.docker compose up -d★Same but detached (background). --detachdocker compose up --buildForce image rebuild before starting.docker compose down★Stop & remove containers, networks. Volumes survive.docker compose down -vdrops dataAlso remove named volumes declared in the file.docker compose stopStop without removing — containers are restartable.docker compose startStart already-created (stopped) containers.docker compose restart [svc]Restart one or all services.docker compose pause / unpauseFreeze/unfreeze container processes.docker compose rmRemove stopped service containers.
docker compose ps★List containers with state, ports, exit codes.docker compose logs★Stream logs from all services.docker compose logs -f --tail 100 svcFollow live logs of one service, last 100 lines.docker compose logs --timestampsAdd ISO timestamps to each log line.docker compose topShow running processes inside each container.docker compose configPrint the resolved, merged compose.yaml — great for debugging env-var substitution.docker compose eventsStream real-time events from containers.docker compose imagesList images used by the stack.
docker compose exec svc sh★Interactive shell in a running container. Use bash if available.docker compose exec -it db psql -U userRun any command interactively inside the service.docker compose run --rm svc cmdSpin up a one-off container, run cmd, then delete it.docker compose cp svc:/path ./localCopy files between container and host.docker exec -w /etc/caddy caddy caddy reloadDirectdocker execalso works with service name from compose.
services: # ← containers to run web: image: nginx db: image: postgres:16★Each key underservices:is one container definition.volumes: # ← named volumes pgdata: # managed by DockerTop-level declaration makes the volume available to services.networks: # ← custom networks backend:Explicit networks let you isolate service groups.configs: # non-secret config data secrets: # sensitive data (Swarm-ready)Mounted read-only into containers at runtime.version: '3.9' # ← DEPRECATEDremove itTheversion:key is obsolete in Compose V2 — omit it.
build: . # Dockerfile in current dir★Shorthand: build context = current directory.build: context: ./backend dockerfile: Dockerfile.prod args: NODE_ENV: production target: production # multi-stageFine-grained build: custom file, build-args, multi-stage target.image: postgres:16.1 image: registry.example.com/app:v2★Pull a pre-built image (local first, then hub/registry).docker compose build --no-cache svcForce clean rebuild of one service's image.docker compose pushPush built images to their configured registry.
ports: - "8080:80" # host:container - "443:443" - "3000" # random host port★portspublishes to the host — reachable from outside the container.expose: - "3000" # documentation onlyexposeis documentation; containers on the same network can already reach each other on any port.ports: - "127.0.0.1:8080:80" # loopback onlyBind to a specific host IP to restrict external access.
environment: POSTGRES_USER: admin POSTGRES_PASSWORD: ${DB_PASS} # from .env DEBUG: "true"★Map form. Use${VAR}to interpolate from host env or.env.environment: - RACK_ENV=development - SESSION_SECRET # pass through from hostList form. A bare name passes the host variable through.env_file: - .env.local - .env.override # later file wins★Load entire env files — great for secrets not committed to git..env vs env_file:common trap.env= Compose substitution only (not in container).env_file:= injected into container. They are different.
volumes: - pgdata:/var/lib/postgresql/data # named volume (Docker manages path)★Named volumes survivedown; Docker stores them under/var/lib/docker/volumes/.- ./data:/data # bind mount - ./config:/etc/cfg:ro # read-only★Bind mounts: you control the host path. Prefixromakes it read-only inside.- /etc/localtime:/etc/localtime:roPass timezone into the container (no TZ env needed).volumes: # top-level section pgdata: # empty = Docker defaults shared: driver: local external_vol: external: true # already existsDeclare volumes at the top level to share across services or reference pre-existing ones.
# All services share a default bridge network. # Reach any service by its service name as DNS. # curl http://db:5432 inside the api container ✓★Docker Compose auto-creates a default network — no config needed for basic stacks.networks: # custom network backend: driver: bridge # in each service: networks: [backend]Custom networks let you control which services can talk to each other.networks: default: external: name: existing-netJoin a network created outside Compose (e.g., a shared proxy network).network_mode: "host" # no isolation network_mode: "none" # fully isolatedSpecial modes:hostshares the host's network stack;nonedisables networking.
depends_on: - db # waits for container startBasic form: waits until the db container is created — not until the app inside is ready.depends_on: db: condition: service_healthy migrations: condition: service_completed_successfully★Condition-based wait:service_healthychecks healthcheck;service_completed_successfullywaits for a one-off task to exit 0.depends_on: db: condition: service_healthy restart: true # re-check if db restartsAdded in Compose v2.20+: restart the dependent service if the dependency restarts.depends_on ≠ readycommon trapWithout a healthcheck + condition,depends_ononly waits for the container process to start — not for the DB to accept connections.
healthcheck: test: ["CMD", "pg_isready", "-U", "user"] interval: 5s # how often to check timeout: 3s # fail if longer than this retries: 5 # mark unhealthy after N fails start_period: 10s # grace period on startup★start_periodgives the app time to boot before failures count againstretries.test: ["CMD", "curl", "-f", "http://localhost/health"] test: ["CMD-SHELL", "redis-cli ping | grep PONG"] test: ["NONE"] # disable inherited checkThree test forms: exec array, shell string, or disable.CMDpreferred (no shell injection risk).
restart: no # default — never restartContainer stays stopped after it exits.restart: always # restart on any exitRestarts on every exit — includingdocker stop. Starts on Docker daemon boot.restart: unless-stopped # ← preferred★Restarts on crash but NOT if you manuallydocker compose stopit. Best for production services.restart: on-failure # non-zero exit only restart: on-failure:3 # max 3 retriesGood for one-off jobs/migrations that should retry on error but not run forever.
command: bundle exec thin -p 3000Override the CMD from the Dockerfile (string form).command: ["node", "server.js", "--port", "3000"]Array form (no shell wrapping — preferred).entrypoint: /app/start.sh entrypoint: ["php", "-d", "vendor/bin/phpunit"]Override the ENTRYPOINT. Also clears the Dockerfile CMD.user: "1000:1000" # uid:gidRun the container process as a specific user — avoid root in production.working_dir: /appSet the working directory inside the container.
labels: com.example.role: "frontend" traefik.enable: "true"Metadata used by Compose, monitoring tools, and reverse-proxy auto-discovery (Traefik, Caddy).extra_hosts: - "host.docker.internal:host-gateway" - "db.local:192.168.1.50"Inject/etc/hostsentries — useful for accessing the host or legacy services.dns: 8.8.8.8 dns: [1.1.1.1, 8.8.8.8]Override DNS resolvers for the container.devices: - "/dev/ttyUSB0:/dev/ttyUSB0"Pass host device nodes into the container (IoT/serial use-cases).extends: file: common.yml service: base-webInherit another service definition — share config across compose files.logging: driver: json-file options: max-size: "10m" max-file: "3"Control the log driver and rotation. Defaultjson-filecan fill disks without limits.
services: api: build: context: . target: production image: myapp:latest ports: ["3000:3000"] env_file: [.env] environment: NODE_ENV: production volumes: [./data:/data] networks: [backend] depends_on: db: {condition: service_healthy} restart: unless-stopped healthcheck: test: ["CMD","curl","-f","http://localhost/health"] interval: 10sA fully annotated, production-style service definition combining the most common options.