DEV Community

Cover image for Simplifying Multi-Container Development with Docker Compose
Mayank Gupta
Mayank Gupta

Posted on

Simplifying Multi-Container Development with Docker Compose

Simplifying Multi-Container Development with Docker Compose

In the last blog post, we built a real-world, multi-container application using Docker. However, managing multiple containers manually with long docker run commands can become repetitive, error-prone, and hard to maintain—especially in teams or CI/CD environments.

This is where Docker Compose comes in. In this post, we’ll explore what Docker Compose is, what it isn’t, how it simplifies development, and how to use it to manage a full stack application with a MongoDB database, Node.js backend, and React frontend.


What is Docker Compose?

Docker Compose is a tool designed to help you define and manage multi-container Docker applications. It uses a YAML file (docker-compose.yml) to configure application services, networks, volumes, and environment variables. With a single command, you can build, start, and run your entire application stack.

Benefits of Docker Compose:

  • Manage multiple containers as a single service
  • Reproducible and consistent development environments
  • Simplifies networking and volume management
  • Easier to share configurations with teams or deploy to staging

What Docker Compose is NOT

It's important to understand what Docker Compose doesn't do:

  • It does not replace Dockerfiles — you still need Dockerfiles to build custom images.
  • It does not replace Docker containers or images — it simply manages them.
  • It is not intended for multi-host orchestration (use Kubernetes or Docker Swarm for that).

Installing Docker Compose (Linux)

If you are using macOS or Windows, Docker Compose is included with Docker Desktop.

For Linux:

sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version
Enter fullscreen mode Exit fullscreen mode

More details: https://docs.docker.com/compose/install/


Practice Resource

Defining Our Application in docker-compose.yml

We’ll build a basic full-stack application with:

  • MongoDB database
  • Node.js backend
  • React frontend
version: "3.8"

services:
  mongodb:
    image: mongo
    container_name: mongodb
    volumes:
      - data:/data/db
    env_file:
      - ./env/mongo.env

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: backend
    ports:
      - '80:80'
    volumes:
      - logs:/app/logs
      - ./backend:/app
      - ./backend/node_modules:/app/node_modules
    env_file: 
      - ./env/backend.env
    depends_on:
      - mongodb

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    container_name: frontend
    ports:
      - '3000:3000'
    volumes:
      - ./frontend/src:/app/src
      - ./frontend/node_modules:/app/node_modules
    env_file:
      - ./env/frontend.env
    depends_on:
      - backend
    stdin_open: true
    tty: true

volumes:
  data:
  logs:
Enter fullscreen mode Exit fullscreen mode

Breaking Down the Services

1. MongoDB Service

Instead of running:

docker run --name mongodb \
  -e MONGO_INITDB_ROOT_USERNAME=max \
  -e MONGO_INITDB_ROOT_PASSWORD=secret \
  -v data:/data/db \
  --rm -d --network goals-net mongo
Enter fullscreen mode Exit fullscreen mode

In Compose:

mongodb:
  image: mongo
  container_name: mongodb
  volumes:
    - data:/data/db
  env_file:
    - ./env/mongo.env
Enter fullscreen mode Exit fullscreen mode

Example mongo.env:

MONGO_INITDB_ROOT_USERNAME=Mayank
MONGO_INITDB_ROOT_PASSWORD=Gupta
Enter fullscreen mode Exit fullscreen mode

2. Backend Service

Instead of manually running build and run commands:

cd backend
docker build -t goals-node .
docker run --name goals-backend --rm -d -p 80:80 --network goals-net goals-node
Enter fullscreen mode Exit fullscreen mode

In Compose:

backend:
  build:
    context: ./backend
    dockerfile: Dockerfile
  container_name: backend
  ports:
    - '80:80'
  volumes:
    - logs:/app/logs
    - ./backend:/app
    - ./backend/node_modules:/app/node_modules
  env_file:
    - ./env/backend.env
  depends_on:
    - mongodb
Enter fullscreen mode Exit fullscreen mode

This also supports live code updates using bind mounts.


3. Frontend Service

Manually:

cd frontend
docker build -t goals-react .
docker run --name goals-frontend --rm -d -p 3000:3000 -it goals-react
Enter fullscreen mode Exit fullscreen mode

With Compose:

frontend:
  build:
    context: ./frontend
    dockerfile: Dockerfile
  container_name: frontend
  ports:
    - '3000:3000'
  volumes:
    - ./frontend/src:/app/src
    - ./frontend/node_modules:/app/node_modules
  env_file:
    - ./env/frontend.env
  depends_on:
    - backend
  stdin_open: true
  tty: true
Enter fullscreen mode Exit fullscreen mode

Running the Application

Start all containers:

docker-compose up
Enter fullscreen mode Exit fullscreen mode

Detached mode:

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Stop and remove containers:

docker-compose down
Enter fullscreen mode Exit fullscreen mode

Stop and remove containers and volumes:

docker-compose down -v
Enter fullscreen mode Exit fullscreen mode

Rebuild images before starting:

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

Advantages of Using Docker Compose

  • One command to run everything
  • Clear declaration of services and dependencies
  • Easily version-controlled with your codebase
  • Enables quick testing and CI integration

Conclusion

Docker Compose helps us streamline multi-container application development by reducing complexity and enabling declarative service definitions. It's ideal for local development, prototyping, and small-scale deployments.

In upcoming blogs, we’ll cover how to use Docker Compose for CI/CD, working with environment-specific files, and Docker Compose for production scenarios.

Explore the source and more projects on my Dev.to profile. If you haven’t checked the first part yet, read it here.

Top comments (0)