homeresume
 
   
🔍

Docker Compose overview

June 20, 2026

Docker Compose runs multi-container applications from a single YAML file. One command can start an API, a database, a message broker, and supporting tools for local development - without installing each service on the host machine.

This post covers Compose concepts and commands. For ready-made stacks, see the service-specific posts linked at the end (Postgres/Redis, RabbitMQ, MongoDB, Kafka, DynamoDB/SQS).

Prerequisites

  • Docker Engine installed
  • Compose V2 - use docker compose (with a space). Current Docker Desktop includes it; no separate Compose install is required.

Mental model

  • Project - the folder that contains docker-compose.yml. The project name defaults to the directory name and prefixes container names.
  • Services - named containers defined in the file (api, redis, postgres). Each service maps to one image or build context.
  • Network - Compose creates a default network so services resolve each other by name. From the api container, Redis is reachable at redis:6379, not localhost:6379.
  • Volumes - named or bind mounts for data that survives docker compose down (unless you pass -v).

Minimal compose file

A two-service stack: a Node API and Redis. No top-level version: key - it is deprecated in the current Compose specification.

services:
api:
build: .
ports:
- 3000:3000
environment:
REDIS_URL: redis://redis:6379
depends_on:
- redis
redis:
image: redis:alpine
volumes:
- redis-data:/data
volumes:
redis-data:

Run docker compose up --build from the directory that contains this file.

Core concepts

Ports - map host ports to container ports as host:container:

ports:
- 3000:3000

Environment - inline variables or an env file:

environment:
REDIS_URL: redis://redis:6379
env_file:
- .env

Volumes - named volumes are managed by Docker (good for database data). Bind mounts map a host path into the container (good for live code reload during development):

volumes:
- redis-data:/data # named
- ./src:/app/src:ro # bind mount

Networks - services on the default network can reach each other by service name. Custom networks isolate groups of services (see the Postgres and Redis post for a multi-network example).

depends_on - controls startup order. It does not wait for the dependency to be ready; add a healthcheck or retry logic in the app when you need readiness.

restart - policies like on-failure:3 or unless-stopped keep containers running after crashes or host reboots.

healthcheck - optional probe so Compose and other services know when a container is ready:

healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 5s
timeout: 3s
retries: 5

Commands

CommandPurpose
docker compose upStart services (foreground, logs in terminal)
docker compose up -dStart in detached mode
docker compose up --buildRebuild images before starting
docker compose downStop and remove containers
docker compose down -vAlso remove named volumes
docker compose psList running services
docker compose logs -f apiFollow logs for one service
docker compose exec api shOpen a shell in a running container
docker compose pullPull latest images

When to use what

ToolBest for
docker runOne-off containers, quick image tests
Docker ComposeLocal multi-service stacks, dev databases and queues
NginxLocal reverse proxy on port 80 in front of Compose or dev servers - see Nginx local setup
KubernetesProduction orchestration, scaling, rolling deploys

Service-specific setups

Demo

Runnable files for this post live in the docker-compose-overview-demo folder. Get access via code demos.

DynamoDB and SQS containers with Docker Compose

June 13, 2026

For Compose basics, see the Docker Compose overview. This post covers DynamoDB Local and ElasticMQ (SQS-compatible) for local AWS-style development.

Prerequisites

  • Docker Compose installed

Configuration

The following configuration spins up DynamoDB Local, DynamoDB Admin, ElasticMQ, and the ElasticMQ UI.

Connection details:

  • DynamoDB endpoint: http://localhost:8000
  • SQS endpoint: http://localhost:9324
  • DynamoDB Admin: http://localhost:8001
  • ElasticMQ UI: http://localhost:3000
  • Region: us-east-1
  • Credentials: any dummy values (for example local / local)
# docker-compose.yml
services:
dynamodb:
image: amazon/dynamodb-local:latest
user: root
command: '-jar DynamoDBLocal.jar -sharedDb -dbPath /home/dynamodblocal/data'
ports:
- '8000:8000'
volumes:
- dynamodb_data:/home/dynamodblocal/data
dynamodb-admin:
image: aaronshaf/dynamodb-admin:latest
ports:
- '8001:8001'
environment:
DYNAMO_ENDPOINT: http://dynamodb:8000
AWS_REGION: us-east-1
AWS_ACCESS_KEY_ID: local
AWS_SECRET_ACCESS_KEY: local
depends_on:
- dynamodb
elasticmq:
image: softwaremill/elasticmq-native:latest
ports:
- '9324:9324'
volumes:
- ./elasticmq.conf:/opt/elasticmq.conf
- elasticmq_data:/data
elasticmq-ui:
image: softwaremill/elasticmq-ui:latest
ports:
- '3000:3000'
environment:
SQS_ENDPOINT: http://elasticmq:9324
depends_on:
- elasticmq
volumes:
dynamodb_data:
elasticmq_data:

ElasticMQ loads queue definitions from an elasticmq.conf file included in the demo.

Run the following command to spin up the containers.

docker compose up -d

Disclaimer

ElasticMQ provides an SQS-compatible API, but it is not AWS SQS. DynamoDB Local also differs from managed DynamoDB (for example capacity modes, streams, TTL, and global tables). Use these containers for local development and integration tests, not as production substitutes.

Demo

Docker Compose files and scripts for this post live in the dynamodb-sqs-docker-compose folder. Get access via code demos.

2024

RabbitMQ container with Docker Compose

September 3, 2024

For Compose basics, see the Docker Compose overview. This post covers a RabbitMQ broker with the management UI.

Prerequisites

  • Docker Compose installed

Configuration

The following configuration spins up the RabbitMQ container with the management UI tool.

The connection string for the RabbitMQ broker with local virtual host is amqp://localhost:5672/local.

RabbitMQ management UI is available at the http://localhost:15672 link. Default credentials are guest as username and guest as password.

# docker-compose.yml
services:
rabbitmq:
image: rabbitmq:3-management
ports:
- 5672:5672
- 15672:15672
environment:
- RABBITMQ_DEFAULT_VHOST=local
volumes:
- 'rabbitmq_data:/data'
volumes:
rabbitmq_data:

Run the following command to spin up the container.

docker compose up

Demo

Docker Compose files and setup scripts for this post live in the rabbitmq-docker-compose folder. Get access via code demos.

MongoDB containers with Docker Compose

February 2, 2024

For Compose basics, see the Docker Compose overview. This post covers MongoDB with Mongo Express.

Prerequisites

  • Docker Compose installed

Configuration

The following configuration spins up the MongoDB container with the UI tool (Mongo Express).

The connection string for the MongoDB database is mongodb://localhost:27018.

Mongo Express is available at the http://localhost:8082 link. Use the below Basic auth credentials to log in to Mongo Express.

# docker-compose.yml
services:
mongo:
image: 'mongo:7.0.5'
ports:
- 27018:27017
volumes:
- my-data:/var/lib/mongodb/data
mongo-express:
image: 'mongo-express:1.0.2'
ports:
- 8082:8081
environment:
ME_CONFIG_BASICAUTH_USERNAME: username
ME_CONFIG_BASICAUTH_PASSWORD: password
volumes:
my-data:

Run the following command to spin up the containers.

docker compose up

Demo

Docker Compose files for this post live in the mongodb-docker-compose folder. Get access via code demos.

2023

Kafka containers with Docker Compose

July 18, 2023

For Compose basics, see the Docker Compose overview. This post covers a single-node Kafka broker in KRaft mode with Kafka UI. Zookeeper is no longer required; it was removed in Kafka 4.0.

Prerequisites

  • Docker Compose installed

Configuration

The following configuration spins up a single-node Kafka broker in KRaft mode with the Kafka UI tool.

The Kafka broker address is localhost:29092, and Kafka UI is available at http://localhost:8085.

# docker-compose.yml
services:
kafka:
image: apache/kafka:4.3.0
hostname: kafka
ports:
- '29092:29092'
environment:
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:29093
KAFKA_LISTENERS: CONTROLLER://:29093,PLAINTEXT://:9092,PLAINTEXT_HOST://:29092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk
kafka-ui:
image: provectuslabs/kafka-ui:latest
ports:
- 8085:8080
depends_on:
- kafka
environment:
KAFKA_CLUSTERS_0_NAME: local
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092

Run the following command to spin up the containers.

docker compose up

Demo

Docker Compose files for this post live in the kafka-docker-compose folder. Get access via code demos.

Postgres and Redis containers with Docker Compose

February 26, 2023

For Compose basics, see the Docker Compose overview. This post covers Postgres and Redis images with UI tools.

Prerequisites

  • Docker Compose installed

Configuration

The following configuration spins up Postgres and Redis containers with UI tools (Pgweb and Redis Commander).

Connection strings for Postgres and Redis are redis://localhost:6379 and postgres://username:password@localhost:5435/database-name.

Pgweb and Redis Commander are available at http://localhost:8085 and http://localhost:8081 links.

# docker-compose.yml
services:
postgres:
image: postgres:alpine
environment:
POSTGRES_DB: database-name
POSTGRES_PASSWORD: password
POSTGRES_USER: username
ports:
- 5435:5432
restart: on-failure:3
pgweb:
image: sosedoff/pgweb
depends_on:
- postgres
environment:
PGWEB_DATABASE_URL: postgres://username:password@postgres:5432/database-name?sslmode=disable
ports:
- 8085:8081
restart: on-failure:3
redis:
image: redis:latest
command: redis-server
volumes:
- redis:/var/lib/redis
- redis-config:/usr/local/etc/redis/redis.conf
ports:
- 6379:6379
networks:
- redis-network
redis-commander:
image: rediscommander/redis-commander:latest
environment:
- REDIS_HOSTS=local:redis:6379
- HTTP_USER=root
- HTTP_PASSWORD=qwerty
ports:
- 8081:8081
networks:
- redis-network
depends_on:
- redis
volumes:
redis:
redis-config:
networks:
redis-network:
driver: bridge

Run the following command to spin up the containers.

docker compose up

Demo

Docker Compose files for this post live in the postgres-redis-docker-compose folder. Get access via code demos.