Automating Infrastructure with Docker Compose
A practical guide to containerizing services and managing them with Docker Compose, from development to production.
This article explores how to use Docker Compose to automate the deployment and management of self-hosted services. We’ll cover the basics of writing a docker-compose.yml file, managing volumes and networks, and setting up a simple production workflow.
Why Docker Compose?
Docker Compose provides a declarative way to define multi-container applications. Instead of running multiple docker run commands, you describe your entire stack in a single YAML file.
Key benefits:
- Reproducibility: The same
docker-compose.ymlworks on any machine with Docker installed. - Simplicity: One command to start, stop, or restart the entire stack.
- Isolation: Services run in separate containers with their own dependencies.
A Basic Example
Let’s start with a simple stack: a web application and a database.
version: "3.8"
services: web: build: ./web ports: - "8080:80" volumes: - ./web:/app depends_on: - db
db: image: postgres:15 environment: POSTGRES_USER: app POSTGRES_PASSWORD: secret volumes: - db_data:/var/lib/postgresql/data
volumes: db_data:This file defines two services:
web: Built from a local Dockerfile, with hot-reload enabled via volume mounting.db: A PostgreSQL container with persistent storage.
To start the stack:
docker-compose up -dTo stop it:
docker-compose downTo stop and remove volumes:
docker-compose down -vBest Practices
Use Named Volumes
Named volumes (like db_data) persist data across container recreation. Avoid binding to host paths for production data.
Environment Variables for Secrets
Never hardcode passwords in docker-compose.yml. Use environment variables:
services: db: image: postgres:15 environment: POSTGRES_PASSWORD: ${DB_PASSWORD}Then run:
DB_PASSWORD=secret docker-compose up -dOr use a .env file (which should be in .gitignore):
DB_PASSWORD=secretHealth Checks
Add health checks to ensure services are actually ready before dependent services start:
services: db: image: postgres:15 healthcheck: test: ["CMD-SHELL", "pg_isready -U app"] interval: 10s timeout: 5s retries: 5Going Further
In future articles, we’ll explore:
- Reverse proxies with Traefik or Caddy
- Secrets management with Docker Swarm or external tools
- CI/CD pipelines for containerized deployments
Conclusion
Docker Compose is a powerful tool for automating infrastructure. Start small, iterate, and gradually add complexity as your needs grow.