How to Configure Docker Compose for Multi-Container Apps: A Practical Guide

Modern applications rarely run in a single container. A typical stack includes a web server, a backend API, a database, and perhaps a message queue. Docker Compose lets you define and run these multi-container setups with a single YAML file, making local development and testing far simpler.

At its core, a docker-compose.yml file orchestrates three key elements: services (your containers), networks (how they communicate), and volumes (persistent data storage). Here’s how to configure each for a robust multi-container application.

Article illustration

1. Declare Your Services Clearly

Each container is a service. Define its image, ports, and environment variables. For a simple web app with a database, your file starts like this:

services:
  web:
    build: .
    ports: - "8080:80"
    environment:
      - DB_HOST=db
  db:
    image: postgres:16
    environment:
      - POSTGRES_PASSWORD=secret

2. Link Services with depends_on and Networks

Use depends_on to control startup order. By default, Compose creates a shared network, giving each service a DNS name matching its service name (e.g., db). For stricter isolation, define custom networks and attach services to them.

services:
  web:
    depends_on:
      - db
    networks: [frontend, backend]
  db:
    networks: [backend]

3. Persist Data with Named Volumes

Database data disappears if its container is removed. Use named volumes to keep data intact across restarts:

volumes:
  dbdata:
services:
  db:
    volumes:
      - dbdata:/var/lib/postgresql/data

4. Run and Manage the Stack

Use docker compose up -d to start everything in detached mode. Check logs with docker compose logs -f, stop with docker compose down, and remove everything (including volumes) with docker compose down -v.

With these configurations, you have a reproducible, scalable foundation for any multi-container project.

sarah antaboga
Author: sarah antaboga

Leave a Reply

Your email address will not be published. Required fields are marked *