What is Docker Compose
Docker Compose is a orchestration and management tool for Docker, which allows you to use a YAML file to configure the service of your application. Through this file, you can define how multiple containers can be connected to each other through the network, and how to configure their environment variables, volume mounts, port mapping, etc. This makes running complex multi-container applications on a single host very simple and intuitive.
Docker Compose mainly solvesdocker run
Instructions anddocker build
The problem of running docker run manually afterwards.
Docker Compose main concepts
-
Services: In the Docker Compose file, a service usually refers to a container. You can define multiple services, each running one or more container instances. For example, your application might contain a web service and a database service.
-
Networks: Docker Compose creates and manages Docker networks so that services can communicate with each other. By default, Docker Compose creates a network for each service, but you can also define custom networks across multiple services.
-
Volumes: Volumes are a mechanism in Docker for persisting data. In Docker Compose, you can define volumes and mount volumes to specific paths within the container so that data is not lost even if the container is deleted.
-
Environment Variables: You can define environment variables for the service, which can be read and used inside the container. This is very useful for configuring the settings of the application.
-
Dependencies: You can define the dependencies of the service in the Docker Compose file to ensure that the service is started in the correct order. For example, you might want to start a database service first and then start a database-dependent service.
Install Docker Compose
Docker Compose project address:/docker/compose
Installation environment information
IP | system | Specification |
---|---|---|
10.0.0.10 | Ubuntu22.04 | 2c4g |
Preparation for installation: Docker is required
Installation steps:
# Download Docker Compose
[root@lb ~]# wget /docker/compose/releases/download/v2.35.0/docker-compose-linux-x86_64
[root@lb ~]# ll docker-compose-linux-x86_64
-rw-r--r-- 1 root root 73664588 Apr 19 14:42 docker-compose-linux-x86_64
# Move to /usr/bin/docker-compose
[root@lb ~]# mv docker-compose-linux-x86_64 /usr/bin/docker-compose
# Grant permissions
[root@lb ~]# chmod +x /usr/bin/docker-compose
[root@lb ~]# ll /usr/bin/docker-compose
-rwxr-xr-x 1 root root 73664588 Apr 19 14:42 /usr/bin/docker-compose*
# examine
[root@lb ~]# docker-compose version
Docker Compose version v2.35.0
Commonly used commands for Docker Compose
There are many commands in Docker Compose. Here are a few commonly used ones. If you encounter new commands later, you will continue to explain them.
Container related
- docker-compose up -d: equivalent to
docker run -d
, create and run containers in the background - docker-compose ps: Check the container running status, only
-q
Options - docker-compose down: delete containers, delete all contents of all containers (network, data volumes)
- docker-compose start: start the container
- docker-compose stop: container closes
- docker-compose restart: restart the container
- docker-compose top: view container process information
- docker-compose logs: view container logs
- docker-compose rm: delete container
- docker-compose exec: Enter the container
Mirror related
- docker-compose pull: pull the service's image
- docker-compose push: push service image
- docker-compose build: build service image
Common commands in Docker Compose files
Official website article:/reference/compose-file/services/
The Docker Compose file is a yaml file, and when running the docker-compose command, there must be a file in the directory where it is located.
services
The Compose file must set services to the top level element.services
The relevant information about specifying the running container can be understood asdocker run
A collection of instructions
Example:
# docker-compose file
[root@lb ~/services]# cat
services:
# Service Name
web:
image: nginx:latest
Ports:
- "8080:80"
# Run the container
[root@lb ~/services]# docker-compose up -d
[+] Running 1/1
✔ Container services-web-1 Started
# View the running container
[root@lb ~/services]# docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
services-web-1 nginx:latest "/docker-entrypoint...." web About a minute ago Up About a minute 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp
image
Specify the basic image of the container runtime
ports
Specify the port number of the container when it is running, and multiple ports can be written
container_name
Specify the name of the container, nocontainer_name
When tagging, it willservices-[services_name]-[services_num]
is the container name
Example:
[root@lb ~/container_name]# cat
services:
web:
image: nginx:latest
# Specify the container name
container_name: nginx_1
Ports:
- "8081:80"
[root@lb ~/container_name]# docker-compose up -d
[+] Running 2/2
✔ Network container_name_default Created 0.1s
✔ Container nginx_1 Started 0.2s
[root@lb ~/container_name]# docker-compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
nginx_1 nginx:latest "/docker-entrypoint...." web 5 seconds ago Up 5 seconds 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp
build
Run Dockerfile, build the image to use, and have several subtitles
context
Specify the directory where the Dockerfile is located
dockerfile
Specify the file name of the Dockerfile, the same asdocker build -f
Directive, this command can be written without writing, default is Dockerfile
Example:
[root@lb ~/build]# cat
services:
zrlog:
container_name: zrlog
# build command
build:
context: ./zrlog
dockerfile: Dockerfile
Ports:
- "8082:8080"
# Build a mirror
[root@lb ~/build]# docker-compose build
Compose can now delegate builds to bake for better performance.
To do so, set COMPOSE_BAKE=true.
[+] Building 6.5s (9/9) FINISHED docker:default
=> [zrlog internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 409B 0.0s
=> [zrlog internal] load metadata for /library/tomcat:9.0.87-jdk8-corretto 6.3s
=> [zrlog internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [zrlog internal] load build context 0.1s
=> => transferring context: 10.80MB 0.1s
=> [zrlog 1/3] FROM /library/tomcat:9.0.87-jdk8-corretto@sha256:6928733a4f4c15d61c45a14b0197fe9a160f49f6f13b1b0b06310561cb320ef0
=> => writing image sha256:0d6bbaa1db8bf9d30e976c17f2991aca20e6b6e070be646b85240e1ec0ffdc71 0.0s
=> => naming to /library/build-zrlog 0.0s
=> [zrlog] resolving provenance for metadata file 0.0s
[+] Building 1/1
✔ zrlog Built 0.0s
# Start the mirror
[root@lb ~/build]# docker-compose up -d
[+] Running 2/2
✔ Network build_default Created 0.1s
✔ Container build-zrlog-1 Started
[root@lb ~/build]# docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
zrlog build-zrlog "run" zrlog About a minute ago Up About a minute (healthy) 0.0.0.0:8082->8080/tcp, [::]:8082->8080/tcp
environment
docker run -e
Options, specify the environment variable after the container is run
Example:
[root@lb ~/environment]# cat
services:
db:
image: mysql:5.7
container_name: mysql_db
Ports:
- "3306:3306"
environment:
# Specify the password of MySQL root
- "MYSQL_ROOT_PASSWORD=root123"
# Specify creating a zrlog database
- "MYSQL_DATABASE=zrlog"
# Run
[root@lb ~/environment]# docker-compose up -d
[+] Running 2/2
✔ Network environment_default Created 0.1s
✔ Container mysql_db Started
# check
[root@lb ~/environment]# docker-compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
mysql_db mysql:5.7 "..." db 14 seconds ago Up 14 seconds 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp
restart
Specify the restart method of the container, anddocker run --restart
Consistent options
Restart method:
- Always: Automatic restart
- unless-stopped: Restart only when the container is closed and stopped
- on-failure: Restart only when failure
Example:
services:
db:
# Specify the restart policy
restart: always
image: mysql:5.7
container_name: mysql_db
Ports:
- "3306:3306"
environment:
# Specify the password of MySQL root
- "MYSQL_ROOT_PASSWORD=root123"
# Specify creating a zrlog database
- "MYSQL_DATABASE=zrlog"
volumes
Official website article:/reference/compose-file/volumes/
The volumes directive has two functions in the Compose file. When used as a top-level element, volume will create a data volume. When used as a child element, it will mount the data volume for the container.
Example:
[root@lb ~/volumes]# cat
services:
db:
# Specify the restart policy
restart: always
image: mysql:5.7
container_name: mysql_db_1
Ports:
- "3307:3306"
environment:
# Specify the password of MySQL root
- "MYSQL_ROOT_PASSWORD=root123"
# Specify creating a zrlog database
- "MYSQL_DATABASE=zrlog"
Volumes:
- mysql_data:/var/lib/mysql
# Create a data volume of mysql_data
Volumes:
mysql_data:
# Start the container
[root@lb ~/volumes]# docker-compose up -d
[+] Running 1/1
✔ Container mysql_db_1 Started # Check 0.3s
[root@lb ~/volumes]# docker-compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
mysql_db_1 mysql:5.7 "..." db 4 seconds ago Up 4 seconds 33060/tcp, 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp
# Check the data volume
[root@lb ~/volumes]# docker inspect mysql_data
[
{
"CreatedAt": "2025-04-12T15:42:17+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mysql_data/_data",
"Name": "mysql_data",
"Options": null,
"Scope": "local"
}
]
When you need to mount to the native host, only the volumes of the secondary element can be used
Example:
services:
web:
image: nginx:latest
volumes:
- ./html:/usr/share/nginx/html
External storage volumes can be used
Example:
services:
web:
image: nginx:latest
Volumes:
- web_data:/usr/share/nginx/html
Volumes:
web_data:
#external specifies that this volume already exists on the platform and its lifecycle is managed by lifecycle outside the application. If the volume does not exist, Compose will not create the volume and return an error.
external: true
healthcheck
healthcheck
A health check mechanism used to define a service. With a health check, you can ensure that the container can run properly after startup and automatically restart or reschedule when the container is unavailable.
Its child elements are:
- test: Commands that define health checks. It can be a command or a script.
- interval: The interval between two health checks (default unit is seconds).
- timeout: The timeout for a single health check.
- retries: The number of retrys after a health check failed.
- start_period: The delay time for the health check to start after the container is started.
Example:
services:
web:
image: nginx:latest
ports:
- "80:80"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
depends_on
depends_on
Used to control the startup order between services. It ensures that the service it depends on is started before starting a service. For example, web services rely on database services, and you can use depends_on when the database service is started first.
Althoughdepends_on
Ensure the order of the service to start, but it will not wait for the service to be fully started before starting the dependent service. For example, the database service may still be in the initialization process, and the web service has been started, which may cause the web application to be unable to connect to the database service. At this time, it needs to be used.healthcheck
depends_on
It will only affect the start order of the container and will not affect the stop order of the container.
Example:
services:
web:
image: nginx:latest
Ports:
- "80:80"
# Specify dependency on db service
depends_on:
db:
condition: service_healthy
db:
image: mysql:latest
environment:
- "MYSQL_ROOT_PASSWORD=root123"
# Health Check
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
links (it has been abandoned on Docker Compose version 3 or above)
links
Is a directive used to define the network connection between services. It allows one service to access the container of another service and communicate through the service name. Although links are very commonly used in earlier versions of Docker Compose, in Docker Compose version 3 and above,links
It has been abandoned and it is recommended to use the default network function to enable communication between services.
What are links?
- Establish a network connection: links is used to establish a network connection between services, allowing one service to access a container for another service.
- Environment variables and /etc/hosts: When using links, Docker automatically sets the environment variables and /etc/hosts entries so that services can communicate through the service name.
Example:
[root@lb ~/links]# cat
services:
web1:
container_name: nginx1
image: nginx:latest
links:
- web2:nginx
Ports:
- "81:80"
web2:
container_name: nginx2
image: nginx:latest
Ports:
- "82:80"
# Run the container
[root@lb ~/links]# docker-compose up -d
[+] Running 3/3
✔ Network links_default Created 0.1s
✔ Container nginx2 Started 0.4s
✔ Container nginx1 Started 0.6s
# examine
[root@lb ~/links]# docker-compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
nginx1 nginx:latest "/docker-entrypoint...." web1 13 seconds ago Up 11 seconds 0.0.0.0:81->80/tcp, [::]:81->80/tcp
nginx2 nginx:latest "/docker-entrypoint...." web2 13 seconds ago Up 12 seconds 0.0.0.0:82->80/tcp, [::]:82->80/tcp
###### Test, enter the container inside nginx1
[root@lb ~/links]# docker exec -it nginx1 bash
# View hosts analysis
root@12b2517e712e:/# cat /etc/hosts
127.0.0.1 localhost
...
# web2 hosts analysis
172.24.0.3 12b2517e712e
root@12b2517e712e:/# curl
curl: try 'curl --help' or 'curl --manual' for more information
root@12b2517e712e:/# curl http://nginx
<!DOCTYPE html>
<html>
# Web page content
</body>
</html>
In Docker Compose version 3 and above, it is recommended to use the default network function to enable communication between services.
Example:
services:
web1:
container_name: nginx1
image: nginx:latest
ports:
- "81:80"
web2:
container_name: nginx2
image: nginx:latest
ports:
- "82:80"
In this example, web1 and web2 are connected to the same network by default, and web1 can directly access the web2 service through the web2 service name
networks
networks
Used to define and manage network communication between services, throughnetworks
Custom networks can be created to connect services to these networks, enabling a flexible network structure.
In Docker Compose, if the network is not explicitly defined, Docker Compose automatically creates a default network for each project and connects all services to that network. The default network isBridge network(bridge network), services can communicate directly through the service name.
You can also customize networks and connect services to these networks, which can be bridges, hosts, or overlays.
Example:
services:
web:
image: nginx:latest
ports:
- "80:80"
networks:
- my_network
db:
image: mysql:latest
environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
networks:
- my_network
networks:
my_network:
driver: bridge
deploy
deploy
Configuration items are used to define the behavior of the service during deployment, including resource limits, number of replicas, update policy, restart policy, etc.
Here we take resource limitations as an example
services:
web:
image: nginx:latest
Ports:
- "80:80"
deploy:
resources:
limits:
cpus: '0.5' # Limit CPU usage to 0.5 cores
memory: 50M # Limit memory usage to 50MB
reservations:
cpus: '0.2' # Reserved 0.2 cores
memory: 20M # Reserved 20MB of memory
limits: defines the maximum amount of resources that a container can use.
- cpus: floating point number, representing the number of CPU cores. For example, 0.5 means a limit to 0.5 cores.
- memory: A string representing memory limit, which can be B (byte), K (kilobyte), M (megabyte), and G (gigabyte).
reservations: defines the amount of resources retained when the container starts.
- cpus: floating point number, representing the number of CPU cores.
- memory: a string, indicating the memory size.
Docker Compose variable file
Compose variable file is inCreated in a directory of the same level
.env
File, in.env
Write to the filekey=value
The form, then inIn the file
${key}
Use in the form of
Example:
[root@lb ~/var]# ll
Total 16
## .env is a variable file
-rw-r--r-- 1 root root 8 Apr 19 21:25 .env
-rw-r--r-- 1 root root 73 Apr 19 21:26
[root@lb ~/var]# cat .env
PORT=83
[root@lb ~/var]# cat
services:
web:
image: nginx:latest
Ports:
## ${PORT} value
- "${PORT}:80"
[root@lb ~/var]# docker-compose up -d
[+] Running 2/2
✔ Network var_default Created 0.1s
✔ Container var-web-1 Started 0.4s
[root@lb ~/var]# docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
var-web-1 nginx:latest "/docker-entrypoint...." web 7 seconds ago Up 6 seconds 0.0.0.0:83->80/tcp, [::]:83->80/tcp
Using multiple compose files
How should we run when we have multiple compose files?
Method 1: Use-f
Options for merge build
When there are multiple Docker Compose files, you can use the docker-compose command-f
Options to specify multiple Compose files and build and manage services together. This way allows you to split configurations into multiple files and then use them in combination.
For example, we have the following two compose files:
services:
web:
image: nginx:latest
ports:
- "80:80"
version: '3.8'
services:
web:
environment:
- NGINX_ENV=prod
db:
image: mysql:latest
environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
We can use the following command to build
docker-compose -f -f up -d
File merge rules:
Docker Compose loads the specified files in order and merges their contents. The merger rules are as follows:
- Services: If the same service is defined in multiple files, the latter configuration overrides the former configuration.
- Networks: If the same network is defined in multiple files, the latter configuration overrides the former configuration.
- Volumes: If the same volume is defined in multiple files, the latter configuration overrides the former configuration.
We can use the docker-compose config command to view the merged configuration. This command will output the final configuration content to help you confirm whether the configuration is correct.
docker-compose -f -f config
Method 2: Useinclude
Elements to refer to other compose files
include
Directives can refer to other Compose files in the main Compose file, thus enabling modularization and reuse of configurations. The referenced file can define services, networks, volumes, etc., and the main file will merge these contents into the final configuration.
Example:
include:
-
services:
serviceA:
build: .
depends_on:
- serviceB
It also supports loading Compose files from remote URLs
include:
- /services/
- /services/
services:
serviceA:
build: .
depends_on:
- serviceB
File merge rules
- Docker Compose loads the files specified in include in order and merges their contents into the main file. The merger rules are as follows:
- Services: If the same service is defined in multiple files, the latter configuration overrides the former configuration.
- Networks: If the same network is defined in multiple files, the latter configuration overrides the former configuration.
- Volumes: If the same volume is defined in multiple files, the latter configuration overrides the former configuration.
Things to note
- File order: The loading order of files in include is very important. The subsequently loaded file will overwrite the configuration in the previously loaded file.
- Local priority: Docker Compose uses local files first if local and remote files have the same path or URL.