What is the need for Docker Compose? #
Running Individual Containers is Repetitive
- Microservices have complex needs: When developing microservices, we often need to run multiple containers together—e.g., a frontend, backend service, database, and other dependencies.
- Repetitive: Running each container individually using
docker run
is repetitive and error-prone- Create and manage shared networks, volumes, ..
- Launch individual containers
- Define and maintain environment variables, port mappings, and restart policies
- Set up service dependencies
Example for Two Microservices
Let’s consider two services: currency-exchange
and currency-conversion
.
currency-exchange
: The Currency Exchange Service provides exchange rates for currency pairs—for example, it can tell you that 1 USD equals 60 INR.currency-conversion
: The Currency Conversion Service uses these rates to calculate conversions (e.g., 10 USD = 600 INR) by calling the Currency Exchange Service and multiplying the result based on the requested quantity.- You want to launch both the services on your local machine
💡 Explore the Microservices
project with detailed guides
Create a Docker Network
docker network create currency-compose-network
Run currency-exchange
Container
docker run -d \
--name currency-exchange \
--network currency-compose-network \
-p 8000:8000 \
--restart always \
in28min/currency-exchange:0.0.1-RELEASE
Run currency-conversion
Container
docker run -d \
--name currency-conversion \
--network currency-compose-network \
-p 8100:8100 \
--restart always \
-e CURRENCY_EXCHANGE_SERVICE_HOST=http://currency-exchange \
in28min/currency-conversion:0.0.1-RELEASE
Clean-up Commands
docker stop currency-conversion currency-exchange
docker rm currency-conversion currency-exchange
docker network rm currency-compose-network
Docker Compose Makes it Simple
- Declarative Approach: Provides a declarative approach to managing multi-container applications.
- Single YAML file with definitions: Define services, networks, volumes, dependencies, and environment variables in one
docker-compose.yml
file - Easy Command to Launch: Bring up the entire stack with a single command:
docker compose up
- Easy Command to Tear Down: Tear everything down cleanly:
docker compose down
- Version Controlled: Maintain a version-controlled setup
- Ensure Consistency: Ensure consistent, reproducible deployments
- Easily Shareable: Easily share your setup with teammates
Summary: Without vs With Compose
Task | Manual Docker Commands | Docker Compose |
---|---|---|
Create Network (Or Volume, ..) | docker network create |
Declared in YAML |
Start Containers | Multiple docker run |
docker compose up |
Set Environment Variables | -e flags |
environment: section |
Manage Dependencies | Manual order handling | depends_on: |
Clean Up | stop , rm , network rm |
docker compose down |
Maintain Consistency | Error-prone | Version-controlled YAML |
How is Docker Compose different from Docker Swarm or Kubernetes? #
Docker Compose vs Docker Swarm vs Kubernetes
- Docker Compose: For local development, testing, and simple setup on a single host.
- Easy local multi-container orchestration
- Use Case: Developers running microservices on their laptop
- Docker Swarm: For lightweight container orchestration across multiple machines
- Docker-native clustering/orchestration
- Use Case: Small-to-medium-scale production deployments where full Kubernetes is overkill (Very rarely used these days!)
- Kubernetes: Enterprise-grade container orchestration at scale.
- Multi-cloud and hybrid deployment support
- Use Case: Large-scale production environments where reliability, scaling, and flexibility are critical
Comparison Table
Feature / Tool | Docker Compose | Docker Swarm | Kubernetes |
---|---|---|---|
Deployment Scope | Single host | Multi-host (cluster) | Multi-host, multi-cloud (cluster) |
Complexity | Low | Medium | High |
Orchestration Support | ❌ | ✅ | ✅✅ |
Ecosystem | Minimal | Limited | Rich and Extensible |
Learning Curve | Easy | Moderate | Steep |
Use Case | Local Dev | Lightweight Prod | Enterprise Production |
Community Adoption | High (developers) | Very low | Very High |
Explain docker-compose.yml, with an example #
docker-compose.yml
- docker-compose.yml: A YAML file where you configure the services that make up your application
- Run Multiple Containers: Enables you to run multiple Docker containers as a single application
Example 1: docker-compose.yml
services:
currency-exchange:
image: in28min/currency-exchange:0.0.1-RELEASE
ports:
- "8000:8000"
restart: always
networks:
- currency-compose-network
currency-conversion:
image: in28min/currency-conversion:0.0.1-RELEASE
ports:
- "8100:8100"
restart: always
environment:
CURRENCY_EXCHANGE_SERVICE_HOST: http://currency-exchange
depends_on:
- currency-exchange
networks:
- currency-compose-network
# Networks to be created to facilitate communication between containers
networks:
currency-compose-network:
Understand it:
services
: Heart of the Docker Compose file. Defines all the containers that will be run.services > container_name > image
: Uses the specified docker image from Docker Hub or a local registry.services > container_name > ports
: Similar to-p
flagservices > container_name > restart: always
: Ensures container automatically restarts if it crashes or host rebootsservices > container_name > networks
: Connects this service to the shared network so it can be discovered by others (e.g., currency-conversion).services > container_name > depends_on
: Tells Docker Compose to start currency-exchange before this service. (Note: doesn’t wait for service to be ready—just started.)services > container_name > environment
: Sets an env variable so the service knows where to contact the currency-exchange microservice. Uses Docker DNS-based service discovery (i.e., http://currency-exchange).
networks
: Defines a custom user-defined bridge networkvolumes
: Defines a custom user-defined volume
Run it:
# Build and Run the Microservices
docker compose up
# Accessing the Microservices
# Currency Exchange API:
curl http://localhost:8000/currency-exchange/from/USD/to/INR
# Currency Conversion API
curl http://localhost:8100/currency-conversion/from/USD/to/INR/quantity/10
# Stopping and Cleaning Up
docker compose down
Another Example: With MySQL Database
- What?: Demonstrates a typical web application and database setup using Docker Compose
- todo-web-application: A Java-based web app that connects to a MySQL database using environment variables.
- mysql: A MySQL container that stores todos data and credentials defined via environment variables.
Notes
- depends_on: The
depends_on
entry ensures that mysql starts before the web application. - mysql-database-data-volume: Ensures data persistence
- Your database files will be retained across container restarts
- Environment Configuration
- mysql: Bootstraps DB, user, and password on startup
MYSQL_ROOT_PASSWORD
: Sets the root (admin) password for MySQLMYSQL_USER
: Creates a new non-root user (todos-user)MYSQL_PASSWORD
: Password for that non-root userMYSQL_DATABASE
: Creates a database namedtodos
and grants access to the above user
- todo-web-application: Read by the app to configure its database connection.
RDS_HOSTNAME
: Hostname of the MySQL server (here, the service name mysql, which Docker Compose resolves automatically via internal DNS)RDS_PORT
: MySQL port (3306 by default)RDS_DB_NAME
: Database name to connect to (todos)RDS_USERNAME
: MySQL username (todos-user)RDS_PASSWORD
: Password used by the app to connect to the DB
- mysql: Bootstraps DB, user, and password on startup
Example 2: docker-compose.yml
services:
todo-web-application:
image: in28min/todo-web-application-mysql:0.0.1-SNAPSHOT
#build:
#context: .
#dockerfile: Dockerfile
ports:
- "8080:8080"
restart: always
depends_on: # Start the depends_on first
- mysql
environment:
RDS_HOSTNAME: mysql
RDS_PORT: 3306
RDS_DB_NAME: todos
RDS_USERNAME: todos-user
RDS_PASSWORD: dummytodos
networks:
- todo-web-application-network
mysql:
image: mysql:5.7
ports:
- "3306:3306"
restart: always
environment:
MYSQL_ROOT_PASSWORD: dummypassword
MYSQL_USER: todos-user
MYSQL_PASSWORD: dummytodos
MYSQL_DATABASE: todos
volumes:
- mysql-database-data-volume:/var/lib/mysql
networks:
- todo-web-application-network
# Volumes
volumes:
mysql-database-data-volume:
networks:
todo-web-application-network:
How can you use Docker Compose to launch and tear down applications? #
Up:
- Builds, (re)creates, starts, and attaches to containers for a service
docker compose up # For detach mode (running in background), use the -d (follow) option docker compose up -d
Down:
- Stops and removes containers, networks, volumes, and images created by up
docker compose down
Restart specific service:
- Command stops and then starts only the specific service without affecting the other running services
docker compose restart <NAME_OF_SERVICE>
Scale services:
- To scale or run multiple instances of the service
docker compose up --scale <NAME_OF_SERVICE>=<NO_OF_INSTANCES> # Example: docker compose up --scale currency-conversion=3
Build:
- Builds or rebuilds services defined in the
docker-compose.yml
docker compose build
services: todo-web-application: image: in28min/todo-web-application-mysql:0.0.1-SNAPSHOT #build: #context: . #dockerfile: Dockerfile
Start:
- Starts existing containers defined in the
docker-compose.yml
docker compose start
Logs:
- View the logs of all services defined in the
docker-compose.yml
docker compose logs # For continuous, real-time logs, you can use the -f (follow) option docker compose logs -f
What is the use of .env files in Docker Compose? #
.env files
- By using
.env
files, you can separate environment-specific configurations from your maindocker-compose.yml
- These files help you manage variables like port numbers, image names, volumes, or environment modes.
- Define and manage environment variables that are used within your
docker-compose.yml
file - Docker Compose automatically loads a
.env
file located in the same directory as yourdocker-compose.yml
1) Base Configuration (docker-compose.yml
):
services:
web:
image: ${NGINX_IMAGE:-nginx}
environment:
- APP_ENV=${APP_ENV}
volumes:
- ${HTML_VOLUME}:/usr/share/nginx/html
ports:
- "${NGINX_PORT}:80"
2) Default .env File (Auto-loaded)
# Development environment
NGINX_IMAGE=nginx:alpine
NGINX_PORT=8080
3) Custom Environment File: dev.env
# Development environment
APP_ENV=development
HTML_VOLUME=./html/dev
4) Command to Use
docker compose --env-file dev.env up
Docker Compose FAQ #
- Q: What happens if you do not specify a network to connect to?
- Container is connected to
default
bridge
network
- Container is connected to
- Q: Difference between
build
andimage
in a service definitionbuild
: Builds image from localDockerfile
image
: Uses an existing image
- Q: How can you pass environment variables to a service in Docker Compose?
- Using
environment:
orenv_file:
in the YAML
- Using
- Q: How can you scale a service using Docker Compose?
docker compose up --scale service_name=3
- Q: Can Docker Compose be used in production?
- Yes for small setups. But lacks advanced orchestration features.
- Kubernetes is better suited for production-scale deployments
- Q: What is the difference between Docker Compose V1 and V2?
- V1: Separate binary, V2: Integrated with Docker CLI
- Syntax - V1:
docker-compose up
, V2:docker compose up
- V2 is the future — it replaces the need for a separate
docker-compose
binary