🐳 Docker Learning Hub
Lesson 8 • Build a small real Docker project
Lesson 8

Build a small real Docker project

This page shows how the earlier Docker topics come together in one beginner-friendly project with an app service, a database service, shared configuration, and persistent storage.

Goal

Build one small setup that looks closer to a real project instead of a single isolated container example.

Services

The project uses an app container and a database container working together through Compose and networking.

Main outcome

You see how Dockerfile, Compose, volumes, networking, and environment variables fit together in one flow.

Project structure

project/ Dockerfile compose.yaml .env package.json server.js

`server.js`

const http = require("http"); const port = process.env.PORT || 3000; const dbHost = process.env.DB_HOST || "db"; const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end(`App is running. DB host is ${dbHost}`); }); server.listen(port, () => { console.log(`Server running on port ${port}`); });

`package.json`

{ "name": "docker-small-project", "version": "1.0.0", "main": "server.js", "scripts": { "start": "node server.js" } }

Dockerfile

FROM node:18 WORKDIR /app COPY package.json /app COPY server.js /app EXPOSE 3000 CMD ["npm", "start"]

`.env` file

PORT=3000 DB_HOST=db NODE_ENV=development MYSQL_ROOT_PASSWORD=rootpass

`compose.yaml`

services: app: build: . ports: - "${PORT}:3000" environment: PORT: ${PORT} DB_HOST: ${DB_HOST} NODE_ENV: ${NODE_ENV} depends_on: - db db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} volumes: - db_data:/var/lib/mysql volumes: db_data:

How the pieces connect

Browser
App container
DB container
Volume keeps DB data persistent

Project flow

Create code and config files
Run `docker compose up --build`
App and DB start together
Open `localhost:3000` to test

Why this project matters

  • It combines the earlier lessons into one realistic setup.
  • The app reads config from environment variables.
  • The database keeps data using a named volume.
  • The app reaches the database using the service name db.

Common beginner mistakes

  • Using localhost instead of db inside the app container.
  • Forgetting the database volume.
  • Hardcoding passwords or hosts directly in app code.
  • Assuming depends_on means the database is fully ready.

What you learned in Lesson 8

Small real projects are connected Docker concepts
A practical setup usually includes code, a Dockerfile, Compose, config, and storage.
Compose ties the system together
It starts both the app and database and keeps the setup easier to manage.
Environment variables keep the setup flexible
The project can change config without changing the application code.
Volumes and networks make the project usable
They handle persistence and service-to-service communication.

Next page: Lesson 9 focuses on Docker debugging and troubleshooting so you can fix common container problems with confidence.