🧩 (Post 3): Docker Compose in Action: Building Multi-Container Apps!

🧩 (Post 3): Docker Compose in Action: Building Multi-Container Apps!

🧩 (Post 3): Docker Compose in Action: Building Multi-Container Apps!

In real-world applications, it's rare to run a single container. You usually have a web app, a database, maybe a caching layer or a reverse proxy. That’s where Docker Compose comes in — your best friend for orchestrating multi-container systems with ease.

📘 What is Docker Compose?

Docker Compose is a tool that lets you define and manage multi-container Docker applications using a single YAML file. With one command, you can bring up or tear down an entire environment.

Benefits:

  • Declarative infrastructure
  • Single file for configuration
  • Built-in networking between containers
  • Volume & env support baked-in

🧾 Writing a docker-compose.yml

Let’s build a stack with:

  • 🔹 nginx as a reverse proxy
  • 🔹 Node.js backend app
  • 🔹 MongoDB database

🛠 Folder structure:

project/
├── nginx/
│   └── default.conf
├── app/
│   ├── Dockerfile
│   └── index.js
├── docker-compose.yml
└── .env

📄 docker-compose.yml

version: "3.9"
services:
  app:
    build: ./app
    environment:
      - MONGO_URL=mongodb://mongo:27017/mydb
    depends_on:
      - mongo
    networks:
      - backend

  mongo:
    image: mongo
    volumes:
      - mongodata:/data/db
    networks:
      - backend

  nginx:
    image: nginx:latest
    ports:
      - "8080:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app
    networks:
      - backend

volumes:
  mongodata:

networks:
  backend:

🔁 Service Dependencies & Health Checks

depends_on ensures order, but doesn’t wait for readiness. To solve that:

Add a healthcheck to your app:

services:
  app:
    ...
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      retries: 3

🔐 Environment Variables & .env

Create a .env file in the root directory:

PORT=3000
MONGO_URL=mongodb://mongo:27017/mydb

Reference inside docker-compose.yml like this:

environment:
  - PORT=${PORT}
  - MONGO_URL=${MONGO_URL}

🧱 App Dockerfile

# app/Dockerfile
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "index.js"]

🧩 Managing the Stack

🚀 Launch all containers:

docker-compose up

🔄 Rebuild after changes:

docker-compose up --build

🛑 Stop everything:

docker-compose down

📈 Scaling Services

You can run multiple containers of a service (useful for APIs):

docker-compose up --scale app=3

💡 Docker Compose will automatically load-balance traffic between them — if your reverse proxy (like Nginx) is configured to do so.

🌐 Sample NGINX Config

# nginx/default.conf
server {
  listen 80;
  location / {
    proxy_pass http://app:3000;
  }
}

This proxies incoming HTTP traffic to our Node.js backend container using its service name as a hostname. Docker’s internal DNS handles it.

📋 Summary

  • 🧩 Docker Compose makes multi-container workflows elegant and maintainable.
  • 🔁 Use depends_on + healthcheck for reliable startup sequences.
  • 🔐 Keep secrets and configs in .env files.
  • 📦 Compose handles volumes, networks, and services all in one place.
  • 🚀 Use docker-compose up --scale to run multiple replicas.

This was your first hands-on dive into orchestrating real-world, production-like setups with Docker Compose.

In our next post, we’ll dive into 📦 (Post 4): Docker Registries: Docker Hub, Private Registry & Image Sharing!

— Blog by Aelify (ML2AI.com)