Docker Compose Tip #73: expose vs ports — what actually gets published

Two directives that look similar but do completely different things. Confusing expose with ports is a classic way to either break inter-service communication or accidentally publish a database to the public internet. What each one does ports publishes a container port to the host. The outside world (and anything on the host) can reach it. services: web: image: nginx ports: - "8080:80" # host:container expose declares that a container listens on a port. It does not publish anything to the host. The directive is documentation of intent for tooling and humans. ...

June 8, 2026 · 3 min · 508 words · Guillaume Lours

Docker Compose Tip #64: Copying files with docker compose cp

Need to grab a log file out of a container? Push a quick config change for a one-off test? Don’t redeploy with a bind mount, just use docker compose cp. Basic usage The syntax mirrors docker cp but resolves service names instead of container IDs: # Copy from container to host docker compose cp <service>:<container-path> <host-path> # Copy from host to container docker compose cp <host-path> <service>:<container-path> The direction is determined by which side has the service: prefix. ...

May 18, 2026 · 2 min · 351 words · Guillaume Lours

Docker Compose Tip #57: Container resource monitoring

A container is running but your app feels sluggish. Is it CPU-bound? Leaking memory? Stuck on a runaway process? Compose gives you two essential commands to find out: docker compose top and docker compose stats. docker compose top Show running processes inside each service’s container: docker compose top myapp-web-1 UID PID PPID C STIME TTY TIME CMD root 12345 12320 0 09:15 ? 00:00:02 nginx: master process nobody 12400 12345 0 09:15 ? 00:00:00 nginx: worker process myapp-api-1 UID PID PPID C STIME TTY TIME CMD node 12500 12480 2 09:15 ? 00:01:45 node server.js node 12600 12500 0 09:15 ? 00:00:12 node worker.js You see every process running inside each container with their CPU usage (C column) and CPU time. Perfect for spotting runaway workers or unexpected child processes. ...

May 1, 2026 · 3 min · 495 words · Guillaume Lours

Docker Compose Tip #54: Preview changes with --dry-run

Not sure what docker compose up will actually do? Add --dry-run to preview every action without executing anything. Basic usage docker compose up --dry-run Compose shows exactly what it would do: DRY-RUN MODE - Container myapp-db-1 Creating DRY-RUN MODE - Container myapp-db-1 Created DRY-RUN MODE - Container myapp-web-1 Creating DRY-RUN MODE - Container myapp-web-1 Created DRY-RUN MODE - Container myapp-db-1 Starting DRY-RUN MODE - Container myapp-db-1 Started DRY-RUN MODE - Container myapp-web-1 Starting DRY-RUN MODE - Container myapp-web-1 Started Nothing is created, started, or modified. You just see the plan. ...

April 17, 2026 · 2 min · 380 words · Guillaume Lours

Docker Compose Tip #53: Compose project name and working directory

Every Compose stack gets a project name. It prefixes all resource names such as containers, networks, volumes. Understanding how it works avoids naming conflicts and makes multi-environment setups cleaner. Default behavior By default, the project name is the directory name where your compose.yml lives: my-app/ compose.yml docker compose up -d # Creates: my-app-web-1, my-app-db-1, my-app_default network Setting the project name Three ways to set it, in order of precedence: # 1. CLI flag (highest precedence) docker compose -p myproject up # 2. Environment variable COMPOSE_PROJECT_NAME=myproject docker compose up # 3. In the Compose file itself # compose.yml name: myproject services: web: image: nginx The name key in the Compose file is the recommended approach, it’s versioned with your code and everyone on the team gets the same project name. ...

April 15, 2026 · 2 min · 385 words · Guillaume Lours