3.2Driving the stack: up, down, logs, ps
The essentials in 30 seconds
- up -d creates everything: networks and volumes, image build/pull, startup in order — --build forces a rebuild after a code change.
- Observe per service, compose-prefixed: compose ps lists the stack, logs -f bdd follows one service, exec web sh goes inside it — never the global docker ps that mixes everything.
- down keeps, -v destroys: down stops and removes containers + network while keeping volumes; down -v also wipes volumes — deliberate reset only.
Running mini-case — Idir and one down too many
Idir, junior DevOps in Algiers, "cleans" his machine with a docker compose down -v before a demo — and wipes the test database filled the day before by his colleague. He adopts the safe cycle: up -d, compose ps, logs -f bdd, exec web sh, down WITHOUT -v by default. On the second up, the database is intact: he has understood that down alone is a safe stop, and that -v is a reset you decide, never a cleanup.
This same case returns in the lesson, the diagram, the script and the 48h challenge.
1. up: build and start, observe: ps, logs, exec
docker compose up -d creates networks and volumes, downloads or builds images, then starts services in order — in the background (-d). Without -d, logs attach to the terminal: handy in development to watch the stack being born, blocking as a service. After a code change, --build forces a rebuild: without it, Compose reuses the existing image and your new code is not picked up.
To SEE: docker compose ps lists the containers OF the project, logs -f bdd follows one service's logs live (with no name, the whole stack, each line prefixed), exec web sh goes inside a container. Golden rule: always prefix with compose — docker ps mixes every project on the machine and makes you diagnose the wrong container.
2. down: safe stop by default, reset by decision
docker compose down stops and removes containers + network, but KEEPS volumes: your data survives, the second up finds it again. This is the safe stop, the everyday one. down -v ALSO wipes volumes: a deliberate reset to start from scratch (test database to reinitialise), reserved for a throwaway or acknowledged stack.
When in doubt: without -v. The classic disaster — down -v "to clean up" before a demo — is avoided with this default. Idir made himself a tattooed rule: down alone to stop, -v only when he can name what he accepts losing. The up → observe → down (without -v) cycle is safe by design.
One cleanup too many
Cleaning up is down alone; -v is moving out.
🔎 Concrete example — Full cycle: the database survives the restart
Idir runs the safe cycle on his web + database stack.
docker compose up -d
docker compose ps
docker compose logs -f bdd
docker compose exec web sh
docker compose down
docker compose up -d # les données sont là
# Reset VOLONTAIRE sur stack jetable uniquement :
# docker compose down -v
Reading: the second up finds the database intact — down alone preserves.
Lesson: down without -v = safe stop; with -v = decided reset, never a cleanup.
Section vocabulary
- up
- Create and start the whole stack: networks, volumes, images (build/pull), containers in order — -d for background.
Simple example: Idir's up -d every morning on the mock-up.
What it is not: starting each container by hand in the right order.
Reflex: --build after each code change.
- down
- Stop and remove containers + network while KEEPING volumes: the safe everyday stop.
Simple example: Idir's evening down, database intact the next day.
What it is not: a stop that wipes the database.
Reflex: down alone by default, always.
- down -v
- down + deletion of VOLUMES: deliberate reset to start from scratch, never a cleanup.
Simple example: The acknowledged reset of a throwaway test database.
What it is not: a "cleanup" before a demo with real data.
Reflex: name what you accept losing before any -v.
- ps (compose)
- List the containers OF the project only — the right scope for diagnosis.
Simple example: compose ps shows Idir's stack, nothing else.
What it is not: global docker ps mixing all projects.
Reflex: always prefix with compose.
- logs -f / exec
- Follow one service's logs live (logs -f bdd) and enter a container (exec web sh).
Simple example: Idir follows the database at startup then inspects the web.
What it is not: guessing the failure without reading logs.
Reflex: ps spots, logs accuses, exec checks.
In practice — Master the cycle without risking data
- Start your stack with -d and list it with compose ps (compare with global docker ps).
- Follow the database logs (logs -f bdd) and enter the web (exec web sh).
- Stop with down, restart: check that the data survived.
- Try down -v on a THROWAWAY stack only, and observe the loss — once is enough.
Ready-to-say script — explaining the cycle to a newcomer (30 s)
"up -d to start, compose ps and logs to observe your stack — never the global ps. And to stop: down alone, the data survives. The -v is a reset that wipes volumes: only on throwaway, never to clean up."
Say during onboarding; run the cycle once together.
Copy-paste template — throwaway training stack
# Stack JETABLE : pour vous entraîner (down -v) sans risque.
services:
web:
image: nginx:1.27
ports:
- "8080:80"
networks:
- bacnet
bdd:
image: postgres:16.4
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- bacdata:/var/lib/postgresql/data
networks:
- bacnet
volumes:
bacdata:
networks:
bacnet:
Freelancer
The up → compose ps/logs → down-alone cycle and your demos survive restarts.
SME in Algiers
Idir trains his colleague: down alone in the evening, database intact in the morning.
Project team
Team rule: -v forbidden except on a named throwaway stack (bac, test).
Beginner
This week: one full cycle + one -v reset on throwaway, to feel the difference.
✓ Best practices
- Always compose + verb (ps, logs, exec) to stay in the project scope.
- down without -v by default; -d as a service, attached only for debugging.
- Add --build after each code change, or mount the code with a bind in dev.
✗ Common pitfalls
- down -v "to clean up": the project's data is wiped.
- docker ps instead of compose ps: you diagnose the wrong container.
- Forgetting --build after a code change: the old image is still running.
Key takeaways
- UP creates everything (-d in background); --build forces a rebuild after a code change.
- PS / LOGS / EXEC per service, always compose-prefixed (project scope).
- DOWN keeps volumes (safe stop); -v destroys them (deliberate reset only).
- The up → observe → down (without -v) cycle is safe by design.
48h challenge — apply tomorrow
Run 1 full cycle on your stack (up -d, ps, logs, exec, down, re-up) and prove the data survives.
- I start in the background and rebuild with --build when code changes.
- I observe per service in the compose scope.
- I stop with down alone; -v only on acknowledged throwaway.
Frequently asked questions
up does not pick up my new code, why?
Because the image is NOT rebuilt: Compose reuses the existing image by default. Add --build (up -d --build) after each code change, or mount the code with a bind mount in development for direct reload. Check with compose ps that the container has just been recreated.
How to follow several services at once?
Run docker compose logs -f with no service name: the whole stack scrolls, each line prefixed with the service name. Ideal at startup to see the real order and spot who fails. Then zoom in with logs -f bdd on the suspect, then exec to go inside.
You want to stop the stack while keeping the database. Which command?