Docker Compose is a container orchestration tool that lets you define and run multi-container applications in a single file. Instead of dozens of commands docker run, you define services in YAML, and Compose starts the entire infrastructure with one command. This guide covers the syntax, key concepts, and practical use cases.
What is Docker Compose
Docker Compose is a command-line tool included with Docker Desktop. It reads a docker-compose.yml file (or compose.yaml) and creates networks, volumes, and containers according to the configuration it describes. Compose is especially useful for local development, when you need to start a database, cache, message queue, and the application itself at the same time.
Key benefits:
- Declarative configuration — all infrastructure is described in one file
- Project isolation — each project gets its own network and container prefix
- Reproducibility — the same environment on every developer's machine
- Simplicity —
docker compose up -dinstead of scripts and documentation
To generate a configuration quickly, use the Docker Compose Builder on reChecker.
Installation and versions
Compose V2 is built into Docker Desktop. On Linux, install the plugin:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install docker-compose-plugin
# Проверка
docker compose versionFiles are compatible with Compose V1 (docker-compose) and V2 (docker compose). V2 is recommended because it supports the Compose Specification and newer features.
Format versions
| Version | Features |
|---|---|
| 2.x | Network support, extended options |
| 3.x | Simplified syntax, Swarm compatibility |
| 3.8+ | Recommended for new projects |
docker-compose.yml structure
A basic file consists of the services, networks, and volumes sections:
services:
app:
image: nginx:alpine
ports:
- "8080:80"
networks:
default:
driver: bridge
volumes:
data:The services section is required. Each service is a container with a name, image, and settings. Networks and volumes are optional, but are often needed for communication between containers and data persistence.
Services: key directives
image and build
services:
# Готовый образ из реестра
db:
image: postgres:16-alpine
# Сборка из Dockerfile
app:
build:
context: .
dockerfile: Dockerfile
image: myapp:latestWhen using build, the image is created on the first run. The image directive sets the name and tag of the build result.
ports and expose
ports:
- "3000:3000" # host:container
- "127.0.0.1:8080:80" # только localhost
- "9000" # случайный порт на хосте
expose:
- "5432" # порт доступен только в сети Composeports publishes ports on the host. expose makes a port visible only to other services on the same network.
environment and env_file
environment:
NODE_ENV: production
DATABASE_URL: postgres://user:pass@db:5432/mydb
- DEBUG=1 # альтернативный синтаксис
env_file:
- .env
- .env.productionVariables from env_file are overridden by values from environment. The .env file in the project root is loaded automatically for value substitution.
volumes
volumes:
- /host/path:/container/path # bind mount
- named_volume:/container/path # named volume
- ./config:/app/config:ro # read-onlyNamed volumes are managed by Docker and preserve data between restarts. Bind mounts map a host directory, which is convenient for development with hot reload.
depends_on
services:
app:
depends_on:
- db
- redis
db:
image: postgres:16
redis:
image: redis:alpineCompose starts containers in dependency order. Important: depends_on does not wait for a service to be ready—PostgreSQL may still be initializing. To wait until a service is ready, use condition: service_healthy with a healthcheck.
healthcheck
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
app:
depends_on:
db:
condition: service_healthyWith condition: service_healthy, the application does not start until the database passes the check. For more on stacks with databases, see Docker Compose for web development.
Networks
By default, Compose creates the projectname_default network. All services get DNS names based on their service names: db, redis, app. Accessing db:5432 from the app container works automatically.
Custom networks:
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # без доступа в интернет
services:
web:
networks:
- frontend
- backend
db:
networks:
- backendThe internal: true network isolates containers from the outside world, which is useful for databases.
Volumes
Named volumes are declared at the root and attached to services:
volumes:
postgres_data:
redis_data:
services:
db:
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
volumes:
- redis_data:/dataData is preserved during docker compose down. To remove everything, use docker compose down -v.
Profiles
Profiles let you run a subset of services:
services:
app:
image: myapp
profiles:
- production
dev-tools:
image: dev-container
profiles:
- dev
db:
image: postgresdocker compose up -d # только db (без профиля)
docker compose --profile dev up # db + dev-tools
docker compose --profile production up # db + appVariables and substitution
Compose supports environment variables in values:
services:
app:
image: myapp:${TAG:-latest}
environment:
DB_HOST: ${DB_HOST:-db}The ${VAR:-default} syntax substitutes a value or a default if the value is missing. The .env file in the project root is loaded automatically.
Useful commands
| Command | Description |
|---|---|
docker compose up -d | Run in the background |
docker compose down | Stop and remove containers |
docker compose ps | List containers |
docker compose logs -f app | Service logs |
docker compose exec app sh | Shell in a container |
docker compose build --no-cache | Rebuild without cache |
docker compose config | Validate and print the merged configuration |
Production recommendations
- Do not store secrets in YAML — use Docker secrets or external systems (Vault, AWS Secrets Manager)
- Limit resources —
deploy.resources.limitsfor CPU and memory - Use healthchecks — for correct
depends_onand monitoring - Version images — do not use
latestin production - Separate configurations —
docker-compose.ymlfor the database,docker-compose.override.ymlfor local overrides
Resource limits
services:
app:
image: myapp:1.0
deploy:
resources:
limits:
cpus: '2'
memory: 1G
reservations:
memory: 256MIn docker compose up mode (without Swarm), the deploy directive may not be applied. Use mem_limit and cpus at the service level for compatibility.
Multiple files
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dThe second file overrides and extends the first. This is convenient for using different environments without duplication.
Advanced use cases
Restart policies
services:
app:
image: myapp
restart: unless-stoppedOptions: no, always, on-failure, unless-stopped. For production, unless-stopped or on-failure is usually used.
Logging
services:
app:
image: myapp
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"This limits the size of logs on disk. Alternatives: syslog, journald, awslogs.
Extending the configuration
The docker-compose.override.yml file is loaded automatically when docker compose up. Use it for local overrides (ports, volumes for source files); do not commit sensitive data.
Debugging and troubleshooting
# Детальный вывод конфигурации
docker compose config
# Запуск с выводом логов
docker compose up
# Проверка зависимостей
docker compose config --servicesIf you have network issues, check docker network ls and docker network inspect. Make sure the services are on the same network.
Migrating from docker-compose to docker compose
Compose V1 (docker-compose) is a standalone binary. V2 (docker compose) is a Docker CLI plugin. The commands are compatible, and the file syntax is the same. To migrate, simply install the plugin and replace the hyphen with a space in commands.
Comparison with alternatives
| Tool | Scale | Complexity | Use case |
|---|---|---|---|
| Docker Compose | 1 host | Low | Development, small deployments |
| Docker Swarm | Cluster | Medium | Orchestration without K8s |
| Kubernetes | Cluster | High | Production, scaling |
Compose is not designed for highly available clusters. Its capabilities are sufficient for a single server or local development.
Docker Compose covers most local development and small deployment use cases. For scalable clusters, consider Kubernetes or Docker Swarm. Get started with the Docker Compose Builder on reChecker—it helps generate a basic configuration for your stack. Ready-to-use stacks for WordPress, Node.js, and PHP are in Docker Compose for web development.