Project 3 of 12 · project brief
The Full Stack in Docker Compose
React, Spring Boot, PostgreSQL, Redis, Kafka, and Nginx running together locally with one command, with health checks, persistence, and environments.
The scenario
New developers take two days to set up ShopLite locally: install Postgres, Redis, Kafka, run the frontend, configure ports. Your brief: one docker compose up that brings up the entire stack in the right order, with realistic data, so a new joiner is productive in 15 minutes.
Before you start
- Docker · Compose fundamentals
Services, networks, volumes.
- Docker · Dependencies & health
Start order that actually waits for readiness.
- Stateful · Kafka fundamentals
Running Kafka in KRaft mode and advertised listeners.
Stack
Target architecture
Deliverables and requirements
You will hand in
compose.yamlwith all services, networks, named volumes, and health checkscompose.override.yamlfor local dev (hot reload, exposed ports) and a.env.example- Database migrations (Flyway) and seed data applied automatically
- A README: prerequisites, one command to start, how to reset data
Functional
docker compose up -dstarts everything; the UI works at http://localhost- Placing an order publishes an event the worker consumes (visible in logs)
- Data survives
docker compose down/up(but notdown -v)
Non-functional
- Services start only when dependencies are HEALTHY (
depends_on: condition: service_healthy) - Only Nginx (80) exposed by default; databases on the internal network
- No secrets in
compose.yaml; values from.env(git-ignored)
Milestones
- 1
Data services with health checks
Done when: Postgres, Redis, and Kafka start and report healthy.
- Postgres with
pg_isreadyhealthcheck and a named volume - Redis with
redis-cli pinghealthcheck - Kafka KRaft single node with a healthcheck using
kafka-topics.sh --list; set advertised listeners for the Compose network
Stuck? Hints
- For Kafka, advertise
kafka:9092for containers; add a second listener onlocalhost:29092only if you need host access.
Prove it works
terminal$ docker compose ps --format 'table {{.Service}}\t{{.Status}}'── expected output ──SERVICE STATUSpostgres Up 40 seconds (healthy)redis Up 40 seconds (healthy)kafka Up 38 seconds (healthy) - Postgres with
- 2
API and worker
Done when: The API connects to all three; migrations and seed data run on startup.
- Build the API image from Project 2
depends_onwithcondition: service_healthy- Flyway migrations in the API; a seed script for demo products
- Worker service consuming
orderstopic
Prove it works
terminal$ curl -s localhost/api/products | jq length; docker compose logs worker | tail -1── expected output ──24worker | Consumed OrderPlaced order-1001 → sending confirmation email - 3
Frontend and Nginx
Done when: React built in a multi-stage image and served by Nginx, which also proxies /api.
- Multi-stage:
nodebuild stage →nginxruntime with thedist/folder - Nginx config:
try_filesfor SPA routing,location /api/proxy toapi:8080
Prove it works
terminal$ curl -sI localhost/ | head -1; curl -s localhost/api/actuator/health── expected output ──HTTP/1.1 200 OK{"status":"UP"} - Multi-stage:
- 4
Developer experience
Done when: Overrides for local dev, a Makefile, and a README.
compose.override.yaml: bind-mount source for hot reload, expose DB ports for local tools- Profiles for optional tools (
--profile toolsadds pgAdmin, Kafka UI) make up,make reset(down -v + up),make logs
Prove it works
terminal$ time (docker compose down -v && docker compose up -d --wait)── expected output ──real 1m12.4s
Would you run this in production?
- ☐Health checks on every service and dependency ordering on health, not just start
- ☐Named volumes for data; documented reset procedure
- ☐No hard-coded secrets;
.env.exampledocuments every variable - ☐Pinned image versions
- ☐Resource limits so one service can't freeze the laptop
Stretch goals
- Add Prometheus + Grafana to the Compose stack (Observability course)
- Use Testcontainers for the API's integration tests (Docker course)
- Add a GitHub Actions job that runs
docker compose up --waitand an end-to-end smoke test
Show it off
Résumé bullet
Built a one-command local environment for a 6-service stack (React, Spring Boot, PostgreSQL, Redis, Kafka, Nginx) with Docker Compose health-gated startup, reducing new-developer setup from 2 days to 15 minutes.
Demo script
make reseton camera, then place an order- Show the Kafka event consumed by the worker
- Kill Redis and show the app degrade gracefully
Interview questions about this project
depends_on doesn't wait for my database to be ready. Why, and how do you fix it?
When is Docker Compose enough, and when do you need Kubernetes?