Unit 5.3 · Tutorial 2

Docker Compose & Networking

Chapter 14 · System Design & Deployment
~2.5 hours Advanced Compose · Networking · Volumes

Overview

Docker Compose is a tool for defining and running multi‑container Docker applications. This tutorial covers writing Compose files, networking containers, managing data with volumes, and orchestrating complex setups with a single command.

Why this matters: Modern applications often consist of multiple services (API, database, cache, frontend). Compose lets you define and run them all together, simplifying development and testing.

1. Docker Compose Fundamentals

Compose uses a YAML file to define services, networks, and volumes.

  • Services: Each container is a service.
  • Networks: Enable communication between containers.
  • Volumes: Persistent data storage.
# Basic commands docker-compose up # Start services docker-compose down # Stop and remove containers docker-compose up -d # Detached mode docker-compose logs # View logs docker-compose exec # Execute in a service docker-compose ps # List running services docker-compose build # Rebuild images

2. Writing a docker-compose.yml

# docker-compose.yml version: '3.8' services: api: build: ./api ports: - "3000:3000" environment: - NODE_ENV=development - DB_HOST=postgres depends_on: - postgres - redis postgres: image: postgres:14 environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: mydb volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:alpine volumes: postgres_data:

Key fields

  • build: Path to Dockerfile.
  • image: Use an existing image.
  • ports: Port mapping.
  • environment: Environment variables.
  • depends_on: Startup order (but not wait for readiness).
  • volumes: Mount volumes.

3. Defining Services

Each service can be configured with its own Dockerfile, environment, and dependencies. You can also scale services horizontally.

# Scale a service docker-compose up --scale api=3 -d # Health checks healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 # Restart policies restart: unless-stopped

4. Networking between Containers

Compose creates a default network for your services. Containers can communicate using service names as hostnames.

# Example: API connects to postgres using 'postgres' hostname # In your app: DB_HOST=postgres # Custom networks networks: frontend: backend: services: api: networks: - frontend - backend postgres: networks: - backend

This isolates services: only the API can access the database, not the frontend (if it were separate).

5. Managing Data with Volumes

Volumes persist data beyond the container lifecycle.

  • Named volumes: Managed by Docker.
  • Bind mounts: Mount a host directory.
  • tmpfs: In‑memory (for temporary data).
# Named volume (persistent) volumes: postgres_data: # Bind mount (for development, hot‑reload) services: api: volumes: - ./api:/app - /app/node_modules # Don't override node_modules # Read‑only mount - ./config:/app/config:ro

Quiz

Question 1

What is the purpose of Docker Compose?

  • To manage a single container
  • To define and run multi‑container applications
  • To build Docker images
  • To manage Kubernetes clusters
Show answer
B. To define and run multi‑container applications.

Question 2

How do containers in a Compose network discover each other?

  • By IP address
  • By service name (hostname)
  • By container ID
  • By manually configuring DNS
Show answer
B. By service name (hostname).

Question 3

Which type of volume is best for sharing code during development with hot‑reload?

  • Named volume
  • Bind mount
  • tmpfs
  • Anonymous volume
Show answer
B. Bind mount (mounts a host directory).

Exercises

Exercise 1

Write a docker-compose.yml for a simple app with a Node.js API and a MongoDB database.

Sample answer
version: '3.8' services: api: build: ./api ports: - "3000:3000" environment: MONGO_URI: mongodb://mongo:27017/mydb depends_on: - mongo mongo: image: mongo:6 volumes: - mongo_data:/data/db volumes: mongo_data:

Exercise 2

Add a Redis cache service to the above Compose file and update the API to use it.

Sample answer
services: api: # ... environment: REDIS_URL: redis://redis:6379 mongo: # ... redis: image: redis:alpine

Homework

Homework 1

Create a Docker Compose setup for your capstone project (frontend + backend + database). Include environment variables, networking, and volumes. Test it locally.

Sample outline
  • Services: React frontend, Node.js API, PostgreSQL DB, Redis cache.
  • Networks: Internal network for backend + DB, external for frontend.
  • Volumes: DB data volume, bind mounts for frontend/backend code (for development).
  • Environment: Use .env file for secrets.

Mini‑Project

Full‑Stack Application with Compose

Build a complete multi‑container application with Docker Compose:

  • React frontend (build and serve with nginx)
  • Node.js backend (Express API)
  • PostgreSQL database
  • Redis cache
  • All services defined in a single docker-compose.yml
  • Use environment variables for configuration
  • Include health checks
Sample outline
  • docker-compose.yml: All services with build contexts.
  • .env: DB credentials, API keys.
  • Frontend: Build React, then serve with nginx.
  • Backend: Node.js with Express, connects to DB and Redis.
  • Health checks: For each service to ensure readiness.

Tutorial Summary

You learned how to use Docker Compose to define and run multi‑container applications. You set up networking between containers, managed data with volumes, and used environment variables. You can now orchestrate complex services with a single command.

Key takeaway: Docker Compose is the standard tool for local development of multi‑service applications. It mirrors production setups, making it easier to test and debug.