Compose 编排
waht & why Compose 编排?
- why Compose 编排?
- 之前我们可以手动单独启动多个容器,因为容器之间默认是隔离的,如果我们需求是这些容器之间需要通信和数据共享,所以我们就需要手动配置网络和配置数据卷来实现这些容器之间的通信和共享数据
- 但由于手动配置是比较繁琐的,Compose 编排就是解决这个问题的,我们只需要在Compose文件中配置好这些容器的网络关系,就可以自动实现这些容器之间的通信。
- what Compose 编排?
- 通过编写Compose文件,多用于把多个镜像组合起来,形成一个应用。
- Compose 编排文件是一个 YAML 文件,用于描述应用的组成和运行方式。
- Compose 编排文件中可以定义多个服务(service),每个服务可以有多个容器(container)。
Compose相关命令
注意
docker compose 命令对于容器的操作多数情况下是在Compose文件所在目录下执行的
| 命令 | 说明 | 适用场景 |
|---|---|---|
docker compose up -d | 后台启动所有服务,自动构建镜像、创建网络/容器 | 日常启动服务(最常用) |
docker compose stop/start/restart | 停止/启动/重启所有服务 | 临时停止服务,后续可重启 |
docker compose down | 停止并删除容器、网络,不删镜像、数据卷 | 清空运行环境,重新部署 |
docker compose logs -f | 实时查看所有服务日志,-f 表示持续刷新 | 排查服务运行报错、查看输出 |
docker compose ps | 查看当前运行的所有服务及状态 | 确认服务是否正常启动 |
docker compose up -d --build | 重新构建镜像,再后台启动服务 | 修改Dockerfile后重新部署 |
docker compose up -d 服务名 | 只后台启动指定单个服务(如mysql) | 单独启动某一个组件 |
docker compose stop 服务名 | 只停止指定单个服务 | 临时停止某一个组件,不影响其他服务 |
docker compose exec 服务名 bash | 进入指定容器内部(交互模式) | 容器内排查问题、执行命令 |
docker compose config | 查看当前compose配置文件详情 | 检查配置是否有误 |
docker compose up -d --force-recreate | 强制重新创建所有容器(不重建镜像) | 容器配置修改后,强制生效 |
docker compose rm | 删除已停止的所有容器 | 清理无用的停止容器 |
Compose 编排LNMP应用实例(WordPress)
- 初始化WordPress应用目录
shell
mkdir lnmp-wps # 创建一个目录,用于存放WordPress应用的配置文件
cd lnmp-wps # 进入WordPress应用目录
touch docker-compose.yml # 创建一个Compose文件
touch Dockerfile-php # 创建一个Dockerfile文件,用于构建PHP镜像
touch nginx.conf # 创建一个nginx配置文件,用于配置nginx服务器 - docker-compose.yml文件内容
yml
services:
# Nginx 服务 - 作为 Web 服务器和反向代理
nginx:
image: nginx:latest # 使用最新版 Nginx 镜像
ports:
- "8080:80" # 将主机的 8080 端口映射到容器的 80 端口
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf # 挂载自定义 Nginx 配置文件
- wp-data:/var/www/html # 共享 WordPress 代码目录(与 PHP 容器共享)
depends_on:
- php # 确保 PHP 容器先启动
restart: always # 容器异常退出时自动重启
# PHP-FPM 服务 - 处理 PHP 动态请求
php:
build:
context: . # 构建上下文为当前目录
dockerfile: Dockerfile-php # 使用指定的 Dockerfile 文件
volumes:
- wp-data:/var/www/html # 共享 WordPress 代码目录(与 Nginx 容器共享)
environment:
# WordPress 数据库连接配置
WORDPRESS_DB_HOST: mysql:3306 # 数据库主机地址(容器名:端口)
WORDPRESS_DB_USER: root # 数据库用户名
WORDPRESS_DB_PASSWORD: 123456 # 数据库密码
WORDPRESS_DB_NAME: wordpress # 数据库名称
depends_on:
- mysql # 确保 MySQL 容器先启动
restart: always # 容器异常退出时自动重启
# MySQL 服务 - 数据库服务
mysql:
image: mysql:8.0 # 使用 MySQL 8.0 版本镜像
environment:
MYSQL_ROOT_PASSWORD: 123456 # root 用户密码
MYSQL_DATABASE: wordpress # 自动创建的数据库名称
volumes:
- mysql-data:/var/lib/mysql # 持久化 MySQL 数据(防止数据丢失)
restart: always # 容器异常退出时自动重启
# 命名卷(Named Volumes)- 用于数据持久化自动创建管理上面mysql和nginx的volume
volumes:
wp-data: # WordPress 代码和上传文件的数据卷
mysql-data: # MySQL 数据库文件的数据卷 - Dockerfile-php文件内容
Dockerfile
#拉取基础镜像
FROM php:8.2-fpm
# 安装 wget + PHP 扩展(关键!)
RUN apt-get update && apt-get install -y wget \
&& docker-php-ext-install mysqli pdo pdo_mysql
# 工作目录 和nginx容器的配置文件目录保持一致(实现数据共享)
WORKDIR /var/www/html
# 下载 WordPress
RUN wget https://wordpress.org/latest.tar.gz && \
tar -zxvf latest.tar.gz --strip-components=1 && \
rm latest.tar.gz
# 设置权限
RUN chown -R www-data:www-data /var/www/html - nginx.conf文件内容
shell
server {
listen 80;
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
} - 启动Compose应用
shell
# 在lnmp-wps目录下执行以下命令启动
docker compose up -d
# 在该目录下执行以下命令查看容器状态
docker compose ps
# 在该目录下执行以下命令查看日志
docker compose logs
- 访问 http://主机IP:8080 即可查看WordPress应用 LAST Question
- 值得一提的是,三个容器是独立的,但是它们为什么可以实现通信?
- 因为Compose默认会创建一个bridge网络,将这三个容器连接到这个网络上,实现相互通信。
- 执行
docker network ls
shell
[root@localhost lnmp-wps]# docker network ls
NETWORK ID NAME DRIVER SCOPE
12d28fd37729 bridge bridge local
abeb326f8566 host host local
4ed2a6ca8e4a lnmp-wps_default bridge local #
db5db577ec9c none null local 可以看到自动创建了lnmp-wps_default的网络,这就是Compose自动创建的bridge网络,将三个独立的容器连接到了这个网络上,实现了相互通信。
网络内部拓展
执行docker network inspect lnmp-wps_default命令查看网络详情
shell
[root@localhost lnmp-wps]# docker network inspect lnmp-wps_default
[
{
"Name": "lnmp-wps_default",
"Id": "4ed2a6ca8e4a1d51a5d7f14cb61a0ef0ff70ae521ad8c82b0dca01a83de5da83",
"Created": "2026-05-05T15:52:05.822979975+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv4": true,
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16", # // 子网
"Gateway": "172.18.0.1" # // 网关
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Options": {},
"Labels": {
"com.docker.compose.config-hash": "af236e8e4687ffd85a14dfaf307f2e37bb8b5650a022e83edbd6e4245c484e9c",
"com.docker.compose.network": "default",
"com.docker.compose.project": "lnmp-wps",
"com.docker.compose.version": "5.1.3"
},
"Containers": {
"569164ad25bd303c21d1950e2d830a3fb4800b882db22a0d2e4a1821461a7ba7": {
"Name": "lnmp-wps-mysql-1",
"EndpointID": "1fecf6f0a10d9b5a04d32a0ef40353a73d5d2654fd2645983f011e803f565a17",
"MacAddress": "02:2c:da:9a:ed:21",
"IPv4Address": "172.18.0.2/16", # // mysql容器IP地址
"IPv6Address": ""
},
"9908f155239f6680f72a9259deff2fe62c254d45b3b9c11383f503d8c5e3d489": {
"Name": "lnmp-wps-nginx-1",
"EndpointID": "58bd143d831879c200e120df66ed30de97b6fa769e04f386f77f2afc758689bd",
"MacAddress": "92:d6:9a:0f:3d:f7",
"IPv4Address": "172.18.0.4/16", # // nginx容器IP地址
"IPv6Address": ""
},
"affe15c2a6d1ffe98a949ea158ee7cba10590bf4baab9d7311ce27531e5c2523": {
"Name": "lnmp-wps-php-1",
"EndpointID": "7c65180cde77954e9e9228d046a70ef32184fe297d75f058a149c6b4fa5afdcb",
"MacAddress": "8a:10:27:b2:67:d7",
"IPv4Address": "172.18.0.3/16", # // php容器IP地址
"IPv6Address": ""
}
},
"Status": {
"IPAM": {
"Subnets": {
"172.18.0.0/16": {
"IPsInUse": 6,
"DynamicIPsAvailable": 65530
}
}
}
}
}
] - 执行
ip a查看宿主机的网络配置
shell
# lnmp-wps_default的对接的虚拟网卡配置
16: br-4ed2a6ca8e4a: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 7a:92:78:14:3a:e3 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-4ed2a6ca8e4a #
valid_lft forever preferred_lft forever
inet6 fe80::7892:78ff:fe14:3ae3/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
# 三个容器的对接宿主机虚拟网卡配置
33: vetha27eabc@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-4ed2a6ca8e4a state UP group default
link/ether ae:9a:c9:16:75:89 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::ac9a:c9ff:fe16:7589/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
34: veth5a1f526@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-4ed2a6ca8e4a state UP group default
link/ether ea:d5:1c:1e:9b:f2 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::e8d5:1cff:fe1e:9bf2/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
35: vethc1029eb@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-4ed2a6ca8e4a state UP group default #
link/ether ca:70:2c:5c:f0:77 brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::c870:2cff:fe5c:f077/64 scope link proto kernel_ll
# 这里是分不清是哪个容器的,需要切入容器内部执行ip a命令查看对应的接口
# 执行`nsenter -t 容器pid -n ip a`命令查看nginx容器的网络配置
[root@localhost lnmp-wps]# nsenter -t 26767 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host proto kernel_lo
valid_lft forever preferred_lft forever
# 这里下面的if35借口就上面数字35开头容器对应的网卡接口
2: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default #
link/ether 92:d6:9a:0f:3d:f7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.4/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever