Introduction
Docker Compose is a powerful tool that simplifies the management of multi-container Docker applications. It allows developers and DevOps engineers to define, configure, and run multiple services using a single YAML file. In this blog, we'll cover Docker Compose in an easy-to-understand way, with real-world examples that you can apply in your DevOps journey.
What is Docker Compose?
Docker Compose is a tool used to define and run multi-container applications. Instead of managing individual docker run
commands, you can use a docker-compose.yml
file to configure and start your entire application stack with a single command.
Why Use Docker Compose?
Simplifies Multi-Container Applications: Manage multiple services using a single file.
Improves Development Workflow: Easily set up and tear down environments.
Supports Networking and Dependencies: Automatically links services together.
Compatible with Different Environments: Use the same configuration for local development and production.
Components of compose file:
version - specifies the version of the Compose file.
services - it the services in your application.
networks - you can define the networking set-up of your application.
volumes - you can define the volumes used by your application.
configs - configs lets you add external configuration to your containers. Keeping configurations external will make your containers more generic.
Installing Docker Compose
Docker Compose is included by default in Docker Desktop for Windows and macOS. For Linux, install it using:
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
ls /usr/local/bin/
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose version
Basic compose commands:
To execute the compose file:
docker-compose up -d
To build the Dockerfile:
docker-compose build
To remove the containers
docker-compose down
To show the configurations of the compose file
docker-compose config
To show the images of the file
docker-compose images
To stop the containers
docker-compose stop
To show the log details of the file
docker-compose logs
To pause the containers
docker-compose pause
To unpause the containers
docker-compose unpause
To see the containers of the compose file
docker-compose ps
Lets write the basic compose file to understand how it works:
Create a file with docker-compose.yaml
name
version: "3"
services:
webapp1:
container_name: container_name
build: <your-Dockerfile-Path>
ports:
- "host_port:container_port"
webapp2:
container_name: container_name
build: <your-Dockerfile-Path>
ports:
- "host_port:container_port"
In the above compose, i am creating 2 services (webapp1, webapp2). For each service we have to provide container_name, path of your Dockerfile and ports to access the application.
Example compose file to create multiple services:
Clone the repo to get the source code
git clone https://github.com/devops0014/compose.git
Now go to folder
cd compose/paytm
you will find 3 folder [“bus-tickets”, “movie-tickets”, “train-tickets”]
lets write the compose file with docker-compose.yml
---
version: "3"
services:
movie:
container_name: movie-container
build: ./movie-tickets
ports:
- "8081:80"
bus:
container_name: bus-container
build: ./bus-tickets
ports:
- "8082:80"
train:
container_name: train-container
build: ./train-tickets
ports:
- "8083:80"
Here is the basic compose file for deploying those 3 services.
lets build the Dockerfiles
docker-compose build
To create the services
docker-compose up -d
Lets check the containers:
docker-compose ps
Now lets check the output for 3 services:
output-1:
output-2:
output-3:
Volumes in Compose File:
In the above example we just used containers and images on our compose file, now lets use volumes for our compose file:
---
version: "3"
services:
movie:
container_name: movie-container
build: ./movie-tickets
ports:
- "8081:80"
volumes:
- movie_volume:/usr/share/nginx/html:ro
bus:
container_name: bus-container
build: ./bus-tickets
ports:
- "8082:80"
volumes:
- bus_volume:/usr/share/nginx/html:ro
train:
container_name: train-container
build: ./train-tickets
ports:
- "8083:80"
volumes:
- train_volume:/usr/share/nginx/html:ro
volumes:
movie_volume:
bus_volume:
train_volume:
Now lets use docker-compose up -d command to create a docker containers, so the containers will recreate with volumes
Now lets check the containers and volumes
docker-compose ps
docker volume ls
Now if you make any changes in volume it will replicated in the output. So lets change the code on docker volumes:
in my output-1: i have Hollywood movie like avengers, now i am changing to Tollywood movies like RRR, PUSHPA & KGF
vim /var/lib/docker/volumes/paytm_movie_volume/_data/index.html
change the menu
I have modified the code on volumes, now we can see the changes on production.
Networks in Compose File:
When we execute the compose file, it will create a network by default for our services.But if you wish to restrict the connection between the services we have to maintain each network for each services individually.
---
version: "3"
services:
movie:
container_name: movie-container
build: ./movie-tickets
ports:
- "8081:80"
volumes:
- movie_volume:/usr/share/nginx/html:ro
networks:
- movie_network
bus:
container_name: bus-container
build: ./bus-tickets
ports:
- "8082:80"
volumes:
- bus_volume:/usr/share/nginx/html:ro
networks:
- bus_network
train:
container_name: train-container
build: ./train-tickets
ports:
- "8083:80"
volumes:
- train_volume:/usr/share/nginx/html:ro
networks:
- train_network
#declare the volumes that you want to create here
volumes:
movie_volume:
bus_volume:
train_volume:
#declare the networks that you want to create here
networks:
movie_network:
driver: bridge
bus_network:
driver: bridge
train_network:
driver: bridge
Lets use docker-compose up -d command to recreate the containers with their own networks.
By using the above command, old containers will gets deleted and new containers will be created with networks.
lets check the networks
docker network ls
you can inspect each container to check the networking configurations.
ENV values in Compose File:
There are several ways you can use environment variables in a Docker Compose file, allowing for flexibility in configuration. Here are some common methods:
1. Using .env
File
create a hidden file called .env
and pass the variables inside the file, now compose fill will automatically get the variables from this .env
file
vim .env
add this data
DB_HOST=mysqldb
DB_PORT=3306
Now lets add the values from .env
file to compose
file
---
version: "3"
services:
movie:
container_name: movie-container
build: ./movie-tickets
ports:
- "8081:80"
volumes:
- movie_volume:/usr/share/nginx/html:ro
networks:
- movie_network
environment:
- DB_SERVER=${DB_HOST}
- DATABASE_PORT=${DB_PORT}
Lets use docker-compose up -d command to recreate the container
Now go to movie-container and check the environment variables inside the container
docker exec -it movie-container bash
use printenv command to see the environment variables
we can see the DATABASE_PORT=3306 and DB_SERVER=localhost. compose file automatically fetch the values from .env file and assign the values into the container.
2. Defining Environment Variables Directly in the docker-compose.yml
You can specify environment variables directly in the environment
section of the docker-compose.yml
file.
open your compose file and add the variables
---
version: "3"
services:
movie:
container_name: movie-container
build: ./movie-tickets
ports:
- "8081:80"
volumes:
- movie_volume:/usr/share/nginx/html:ro
networks:
- movie_network
environment:
- DB_ENDPOINT=https://mysqldb..com
- DB_USER=root
In the above file i directly assigned the values on compose file.
3. Using Shell Environment Variables
If you have environment variables set in your shell (e.g., in your terminal session), you can reference those in the docker-compose.yml
file.
To use this, you need to have the environment variables already set in your docker host:
on your docker host perform this commands to export variables
export DB_NAME=mustafa
export DB_PORT=3306
---
version: "3"
services:
movie:
container_name: movie-container
build: ./movie-tickets
ports:
- "8081:80"
volumes:
- movie_volume:/usr/share/nginx/html:ro
networks:
- movie_network
environment:
- DB_NAME=${DB_NAME}
- DB_PORT=${DB_PORT}
Lets use docker-compose up -d command to recreate the container.
containers inside will hold the values DB_NAME=mustafa & DB_PORT=3306 . Now this time compose file get the values from docker host which we export.
In my next blog i am going to revel with real time application deployments using docker compose and also nginx reverse proxy and scaling using docker compose.
Conclusion
Docker Compose simplifies managing multi-container applications with declarative configuration, automated networking, and easy scaling. It is an essential tool for DevOps engineers, helping streamline deployments in development and test environments.
By mastering Docker Compose, you can efficiently manage containerized applications and prepare for real-world DevOps challenges.
Give me your heart 💖
If you found this blog helpful for your interviews or in learning Docker troubleshooting, please hit a heart for 10 times and drop a comment! Your support motivates me to create more content on DevOps and related topics. ❤️
If you'd like to connect or discuss more on this topic, feel free to reach out on LinkedIn.
Linkedin: linkedin.com/in/musta-shaik