A hands-on lab documenting the orchestration of a multi-container application using Docker Compose — from cloning source code to a live, database-backed web app.
Project Overview
This lab covers the containerization and orchestration of a multi-service web application using Docker Compose. The project clones a real-world Node.js to-do list application backed by a MySQL database, defines both services declaratively in a single compose.yaml file, and brings the entire stack online with one command — demonstrating core DevOps skills in container orchestration, service networking, and persistent data management. Two real configuration errors were also encountered and resolved along the way, since debugging is as much a part of the DevOps process as the happy path.
Tools & Technologies
- Docker Desktop — container runtime and management UI
- Docker Compose — multi-container orchestration (compose.yaml)
- Node.js (node:22-alpine) — application server image
- MySQL 8.0 — relational database with a persistent named volume
- Git — cloning the application source from GitHub
- VS Code + PowerShell — local development and terminal environment
Architecture at a Glance
The compose.yaml file defines two services on a shared Docker network: an app service built from the node:22-alpine image and exposed on port 3000, and a mysql service running MySQL 8.0 with its data persisted to a named volume (todo-mysql-data) so records survive container restarts. Environment variables provision the database root password and create the todos database automatically on first boot, letting the entire stack start with a single docker compose up command.
Step-by-Step Walkthrough
Step 1 — Clone the Application Source Code
Work began in a fresh DOCKER COMPOSE working directory inside VS Code. The first clone attempt used a malformed URL (missing the // after the protocol), which Git misread as an SSH host reference, producing a "Could not resolve hostname" error. Correcting the URL to a proper HTTPS format resolved the issue immediately.
git clone https://GitHub.com/dockersamples/todo-list-app # failed — bad URL
git clone https://GitHub.com/dockersamples/todo-list-app # corrected
cd todo-list-app
Troubleshooting note: git clone requires a well-formed protocol (https://); a single missing slash caused Git to treat the URL as an SSH remote instead of HTTPS.
Step 2 — Review the Docker Compose Configuration

With the source cloned, compose.yaml was opened to inspect the service definitions. The mysql service specifies a persistent named volume (todo-mysql-data) so database data isn't lost when the container restarts, along with environment variables that set the root password and auto-create the todos database on first startup.
Step 3 — Build and Start the Multi-Container Stack

Running docker compose up from the parent DOCKER COMPOSE folder failed with "no configuration file provided: not found", since Compose looks for compose.yaml in the current directory. Moving into the todo-list-app project folder and re-running the command resolved it: Compose pulled the node:22-alpine and mysql:8.0 images, created a dedicated network and volume, and started both containers successfully.
docker compose up -d --build # failed — wrong directory
cd todo-list-app
docker compose up -d --build # succeeded — 19/19 steps
Troubleshooting note: docker compose commands must be run from the directory containing compose.yaml (or with the -f flag pointing to it).
Step 4 — Verify the Running Containers in Docker Desktop


Switching to Docker Desktop's Containers view confirms the todo-list-app project group is live, with two healthy containers: app-1 running node:22-alpine and mapped to port 3000, and mysql-1 running mysql:8.0. Both show active CPU and memory usage, confirming the stack is up and communicating over its internal Docker network.
Step 5 — Test the Live Application

Finally, browsing to localhost:3000 confirms the full stack is working end-to-end: the Node.js frontend renders and reads/writes to-do items that are persisted in the MySQL container, with add, check-off, and delete actions all functioning against the live database.
Outcome
Starting from a cloned repository, this lab produced a fully functional, networked two-container application — a Node.js frontend and a MySQL database — orchestrated entirely through a single Docker Compose file and brought online with one command. Two realistic configuration errors were hit and resolved along the way, mirroring the kind of debugging that happens in real container deployments.
Skills Demonstrated
- Cloning and configuring application source repositories with Git
- Authoring and reading multi-service Docker Compose definitions
- Container orchestration: networks, named volumes, and service dependencies
- Environment-variable-driven database provisioning (MySQL)
- Debugging common Docker CLI and Git configuration errors
- Verifying containerized services through Docker Desktop and browser testing

Top comments (0)