I'll be honest: I had read about Docker containers probably five times before anything clicked. The diagrams made sense in isolation, but I couldn't picture how a real application actually used any of it. What does a network between containers look like in practice? What does a volume actually do?
For one of our DevSecOps assignments, we were pointed to Samuel Nartey's DockerQuiz project — a Kahoot-style Docker quiz that is itself a fully containerized 3-container application. The premise was simple and smart: learn Docker by running Docker, not by reading about it.
This is my honest write-up of building it, breaking it, and what I actually learned along the way.
What the Project Is
DockerQuiz is a Flask web app that quizzes you on Docker concepts. But the real lesson isn't the quiz — it's the infrastructure underneath it.
When you run docker compose up, three containers spin up and connect over a private network:
quiz-app — the Flask application serving the quiz atlocalhost:5000
mongo — a MongoDB instance storing your profiles, scores, and session state
mongo-express — a web UI for browsing MongoDB live atlocalhost:8081
┌─────────────────────────────────────────────────────────────────┐
│ quiz-network (bridge) │
│ │
│ ┌──────────────┐ ┌───────────────┐ ┌──────────────┐ │
│ │ quiz-app │─────▶│ mongo │◀───│mongo-express │ │
│ │ Flask :5000 │ │ MongoDB :27017│ │ Web UI :8081 │ │
│ └──────────────┘ └───────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Three separate containers. One shared network. One command to start everything.
Getting It Running
Prerequisites: Just Docker Desktop
No Python, no MongoDB, no Node.js installation needed. Everything runs inside containers. That alone felt like a small revelation — my machine didn't need to know anything about Flask or MongoDB. Docker handled all of it.
After cloning the repo and navigating into the project folder, I ran:
docker compose up --build
The first run took a few minutes — Docker was pulling the official mongo:7.0 and mongo-express:1.0.2 images from Docker Hub. After that, every subsequent run took a matter of seconds.
Once the terminal showed quiz-app | * Running on http://0.0.0.0:5000, I opened two tabs:
http://localhost:5000— the quiz
http://localhost:8081— Mongo Express
The quiz interface at localhost:5000
_My profile document appearing in the profiles collection
_
The quiz app now accessible at port 8000
Commented out depends_on
Running docker compose down to stop all containers
What I Actually Walked Away Understanding
Before this project, I could define Docker concepts. After it, I understood them:
Container networking — Containers on the same network talk to each other by service name. mongo resolves to the MongoDB container because Docker's internal DNS makes it so. No IP addresses, no host machine involvement.
Port mapping — The container's internal port and the host port are completely independent. "8000:5000" means "my machine's 8000 talks to the container's 5000." Changing the host side changes nothing inside the container.
Named volumes — mongo-data:/data/db means data written inside the container at /data/db is actually stored in a Docker-managed volume on the host. That's why your quiz results survive a restart.
depends_on vs. actual readiness — Start order is not the same as service readiness. Your application needs to handle the case where its dependencies aren't immediately available. Retry logic matters.
Why multiple containers — The separation between quiz-app, mongo, and mongo-express isn't over-engineering. It means you can update the Flask app without touching the database. You can scale the app without scaling the database. You can swap MongoDB for something else without rewriting application code. This is the architecture pattern that shows up in real production systems.
Try It Yourself
The full project is here: github.com/samuel-nartey/devops-labs
Navigate to Docker & Containers/Running Your First Container/running docker compose, run docker compose up --build, and play through it yourself. Then open docker-compose.yml and start experimenting. The experiments in the README are genuinely worth doing — even when (especially when) they don't produce the failure you expected.
Docker clicked for me when I stopped reading about it and started running something real. This project is exactly that.
SOCIAL SHARE CARD GENERATOR