docker docker-compose containers devops tutorials

How to Use Docker Compose for Multi-Container Deployments

Learn Docker Compose from scratch. Build multi-container apps with YAML configs, examples & commands.

Kodetra TechnologiesKodetra Technologies
3 min read
Dec 18, 2025
1 views

Docker Compose is a powerful tool that simplifies the process of managing multi-container Docker applications. Instead of running multiple docker run commands, you can define all your services in a single YAML file and start everything with one command. This guide will walk you through the essentials of Docker Compose for building scalable applications.

Why Use Docker Compose?

  • Simplified configuration: Define your entire multi-container setup in a single docker-compose.yml file
  • Easy scaling: Scale services up or down with one command
  • Consistent environments: Ensure development, testing, and production environments match perfectly
  • Network isolation: Automatically creates a network for your services to communicate securely

Creating Your First Docker Compose File

Let's create a simple multi-container application with a Node.js web server and a MongoDB database. Create a file named docker-compose.yml in your project directory:

version: '3.8'

services:
  web:
    image: node:18-alpine
    working_dir: /app
    volumes:
      - ./app:/app
    ports:
      - "3000:3000"
    environment:
      - MONGO_URL=mongodb://mongodb:27017/myapp
    command: npm start
    depends_on:
      - mongodb
  
  mongodb:
    image: mongo:7
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db

volumes:
  mongo-data:

Understanding the Configuration

version: Specifies the Compose file format version

services: Defines the containers that make up your application

  • web: Your Node.js application containerUses the official Node.js 18 Alpine image (lightweight)Mounts your local ./app directory to /app in the containerExposes port 3000Sets environment variable for MongoDB connectionDepends on mongodb service to start first
    • Uses the official Node.js 18 Alpine image (lightweight)
    • Mounts your local ./app directory to /app in the container
    • Exposes port 3000
    • Sets environment variable for MongoDB connection
    • Depends on mongodb service to start first
  • mongodb: Your database containerUses official MongoDB 7 imageExposes port 27017Uses a named volume for persistent data storage
    • Uses official MongoDB 7 image
    • Exposes port 27017
    • Uses a named volume for persistent data storage

volumes: Named volumes for persistent data that survives container restarts

Running Your Application

Start your application with:

docker-compose up -d

The -d flag runs containers in detached mode (background).

View logs in real-time:

docker-compose logs -f

Stop and remove all containers:

docker-compose down

To stop and remove containers along with volumes:

docker-compose down -v

Common Docker Compose Commands

Scale services: Run multiple instances of a service

docker-compose up -d --scale web=3

View running services:

docker-compose ps

Execute commands in a running container:

docker-compose exec web npm install

Rebuild containers after changing code:

docker-compose up -d --build

View resource usage:

docker-compose stats

Environment Variables and Configuration

Create a .env file in your project root to manage environment-specific configurations:

NODE_ENV=production
DB_USER=admin
DB_PASSWORD=secretpassword
APP_PORT=3000

Reference these in your docker-compose.yml:

services:
  web:
    environment:
      - NODE_ENV=${NODE_ENV}
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
    ports:
      - "${APP_PORT}:3000"

Best Practices

  1. Always specify image versions: Use node:18-alpine instead of node:latest to ensure consistency
  2. Use environment variables: Keep configuration separate from code
  3. Implement health checks: Ensure containers are actually ready before marking them as healthy
  4. Use volumes for persistent data: Never store important data only in containers
  5. Set resource limits: Prevent containers from consuming all system resources
  6. Use named volumes: Easier to manage than anonymous volumes
  7. Organize with profiles: Use profiles for development vs production configurations
  8. Keep secrets secure: Never commit sensitive data to version control

Adding Health Checks

Improve reliability by adding health checks to your services:

services:
  web:
    image: node:18-alpine
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Multi-Environment Setup

Use multiple compose files for different environments:

docker-compose.yml (base configuration)docker-compose.dev.yml (development overrides)docker-compose.prod.yml (production overrides)

Run with specific configuration:

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Troubleshooting Common Issues

Container won't start: Check logs with docker-compose logs <service-name>

Port already in use: Change the port mapping or stop the conflicting service

Volume permission issues: Ensure proper user permissions in your Dockerfile

Network connectivity issues: Verify service names match in your connection strings

Database connection fails: Ensure depends_on is set and services are healthy

Conclusion

Docker Compose simplifies multi-container application management by providing declarative configuration and powerful orchestration features. Start with simple configurations like the example above and gradually add complexity as your application grows. With proper use of Docker Compose, you can achieve consistent, reproducible deployments across all environments - from local development to production.

The key benefits you'll experience are faster development cycles, easier collaboration with team members, and more reliable deployments. As you become comfortable with Docker Compose, explore advanced features like custom networks, build arguments, and extension fields to further optimize your workflow.

Share:

Loading comments...