DevOps Project
Multi-Service Docker App
Most tutorials containerise one service, which hides everything hard about containers. A multi-service application forces you to solve networking, startup order, health checks, shared configuration and persistent volumes — the problems that actually appear when you deploy something real.
The brief
Build a system of at least four services that start with one command, survive a restart with their data intact, and report their own health. Background work must run off the request path.
What it demonstrates
That you can reason about a system rather than a program — dependencies, failure order and state that must outlive a container.
What "done" looks like
Build all of these and the project is finished. Anything past that is in the stretch goals.
- At least four services — web, API, worker, database, cache
- One command to start the whole system
- Data that survives a restart
- Health checks on every service
- Background work processed off the request path
- Configuration by environment, with no secrets in the repository
How to build it
- 1
Containerise each service alone
Get each one running in isolation first. Debugging four broken containers at once is not a strategy.
- 2
Compose them
One file defining services, networks and volumes. Services reach each other by name, not by IP.
- 3
Persist state in named volumes
Never inside the container filesystem. Restart the stack and confirm the data is still there.
- 4
Add health checks and retries
depends_on waits for a container, not a ready service — so the API must retry its database connection.
- 5
Add the queue and worker
Move slow work off the request path. This is the point at which it becomes a system rather than an app.
- 6
Put a proxy in front
Nginx routing to web and API on one port, so the stack presents a single entry point.
- 7
Centralise logs and config
Structured logs to stdout, configuration by environment variable. Then prove a fresh clone starts with one command.
Once it works
Only after the definition of done is met. Half-finished ambition reads worse than a small finished thing.
- Add Prometheus and Grafana for metrics
- Add a separate production compose file with tuned settings
- Port it to Kubernetes and write up what actually changed
Frequently Asked Questions
How do I handle service startup order?
Health checks and retries, not sleeps. `depends_on` waits for a container to start, not for the service inside it to be ready — so your API must retry its database connection. Building that retry is the correct fix and it is what production requires anyway.
Where does data live?
Named volumes, never inside the container filesystem. A container is disposable by design, and discovering that by losing your database is a memorable but avoidable lesson.
Should I use Kubernetes instead?
Not for this. Compose teaches the same concepts — networking, volumes, configuration, health — without also making you operate a cluster. Learn this first; Kubernetes then makes sense instead of feeling arbitrary.