使用docker-compose对多容器应用进行管理
- [TIPS0:docker compose安装](#TIPS0:docker compose安装)
- [TIPS1:关于docker compose语法版本](#TIPS1:关于docker compose语法版本)
- [TIPS2:关于docker compose中的缩进](#TIPS2:关于docker compose中的缩进)
- [一.为什么要 Docker Compose及其适用场景](#一.为什么要 Docker Compose及其适用场景)
-
- [docker compose功能](#docker compose功能)
- 适用场景
- [二.docker compose文件基本结构及常见指令](#二.docker compose文件基本结构及常见指令)
- [三.使用docker compose搭建一个wordpress站点](#三.使用docker compose搭建一个wordpress站点)
TIPS0:docker compose安装
默认我们安装docker时就已经安装过docker compose了,我的版本是5.0.0的版本是比较新的版本,所以 docker compose的安装我们不再赘述:
bash
knd@NightCode:~/dockertest$ docker compose version
Docker Compose version v5.0.0
TIPS1:关于docker compose语法版本
docker compose语法版本目前官方支持三个大版本, 即 Version 1、 Version 2 及 Version 3, 其中 Version 1 已经被废弃掉了。
截至目前(2025 年末),Docker Compose 最"新的语法版本"并不是一个单独的数字版本号(比如以前的 version: "3.9" 那样),而是由 Compose Specification(Compose 文件规范) 来定义的最新规范。最新的 Docker Compose 工具默认使用 最新的 Compose Specification 语法。
不再推荐在 docker-compose.yml 顶部写 version: 字段:在 Docker Compose 最新版本(V2 及以上)中,这个字段已被视为 过时(deprecated/obsolete),工具会忽略它,并使用最新的规范解析文件。
Compose Specification 是当前的官方规范:它整合了旧的 2.x / 3.x 版本,并持续更新,是官方推荐的 Compose 文件格式定义标准。
实际 Compose 工具版本最新为 V5 系列:官方最近发布了 Docker Compose V5(如 v5.0.1),这表明当前 CLI/插件已是最新主线版本。
所以我们写docker-compose.yml时,不再需要去纠结指定那个版本了,你带和不带version都是不影响的,毕竟他是向后兼容的,而docker compose也会自动忽略version字段。
docker-compose语法官方文档
TIPS2:关于docker compose中的缩进
Docker Compose 文件使用 YAML(YAML Ain't Markup Language) 格式。
- 使用空格,不要用 Tab 键
- 推荐使用 2 个空格 作为一级缩进(这是 Docker 官方示例中的常见做法)
- 也可以使用 4 个空格,但要保持全文一致
其他需要注意加空格的地方:
- 冒号后必须加空格:key: value
- 列表项用短横线:前面加空格 - item
建议大家编写的时候比如你使用vscode或trae或cursor装个插件,这样就不用操心缩进的问题了。当然也可以搜索些在线工具让其帮你调整缩进。
一.为什么要 Docker Compose及其适用场景
- Docker 是一个轻量化的应用程序, Docker 官方推荐每个 Docker 容器中只运行一个进程。
- 如果一个应用需要涉及到 MySQL、 nginx 等环境, 那么我们需要分别为应用、数据库和 nginx 创建单独的 docker 容器,然后分别启动容器。
- 想象一下,当我们构建好 Docker 之后,每次启动应用,都至少需要 docker run三次, 或者写一些脚本来实现, 这样会比较繁琐。
- 另外,这些 docker 容器都是分散独立的,也不方便镜像管理。那既然这些 docker容器 都是为了同一个应用服务,我们就应该把它们放到一起,这就引出了 dockercompose 来解决这类型的问题。
docker compose功能
使用步骤
Compose 使用的步骤:
- 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
- 最后,执行 docker compose up 命令来启动并运行整个应用程序。
核心功能
Compose 具有管理应用程序整个生命周期的命令:
- 启动,停止和重建服务
- 查看正在运行的服务的状态
- 流式传输运行服务的日志输出
- 在服务上运行一次性命令
适用场景
单主机部署
快速搭建一个单节点开发或者测试环境,方便使用。
不同环境隔离
通过指定 project 来运行不同的环境,实现隔离的目的。
二.docker compose文件基本结构及常见指令
2.1基本结构
yaml
version: "3.8" # 定义版本, 表示当前使用的 docker-compose 语法的版本
services: # 服务,可以存在多个servicename: # 服务名字,它也是内部 bridge 网络可以使用的 DNS name,
如果不是集群模式相当于 docker run 的时候指定的一个名称,
#集群(Swarm)模式是多个容器的逻辑抽象
image: # 必选,镜像的名字
command: # 可选,如果设置,则会覆盖默认镜像里的 CMD 命令
environment: # 可选,等价于 docker container run 里的 --env 选项
设置环境变量
volumes: # 可选,等价于 docker container run 里的 -v 选项 绑定数据
卷
networks: # 可选,等价于 docker container run 里的 --network 选项
指定网络
ports: # 可选,等价于 docker container run 里的 -p 选项指定端口映
射
expose: # 可选,指定容器暴露的端口
build: #构建目录
depends_on: #服务依赖配置
env_file: #环境变量文件
servicename2:
image:
command:
networks:
ports:
servicename3:
#...
volumes: # 可选,等价于 docker volume create
networks: # 可选,等价于 docker network create
2.2常见指令
image
指定容器运行的镜像。以下格式都可以:
yaml
image: redis
image: redis:5
image:
redis@sha256:0ed5d5928d4737458944eb604cc8509e245c3e19d02ad83935398
bc4b991aac7
image: library/redis
image: docker.io/library/redis
image: my_private.registry:5000/redis
我们这里做个示例,我们来使用docker compose启动一个nginx服务:
yaml
services:
nginx:
image: nginx:1.29.4
这里我们先学习两个docker compose的命令,docker compose up会默认读取当前目录下的docker-compose.yml文件并根据文件内容进行docker的相关操作,加上-d选项可以让服务后台运行。docker compose down会默认读取当前目录下的docker-compose.yml,对相关服务进行停止并删除,注意down会把项目创建好的容器,自定义网络等等全部删除。我们来运行下上面的docker-compose.yml来看看:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj1$ sudo docker compose up -d
[+] up 2/2
✔ Network prj1_default Created 0.0s
✔ Container prj1-nginx-1 Created 0.1s
这时我们来看看容器与自定义网络:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj1$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
825f3aba88a2 bridge bridge local
85f54d235a1c host host local
e3fb4a996c23 none null local
dc5562e0ef33 prj1_default bridge local
knd@NightCode:~/dockertest/dockercompose_test/prj1$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9bd635658b01 nginx:1.29.4 "/docker-entrypoint...." 49 seconds ago Up 48 seconds 80/tcp prj1-nginx-1
如果我们使用docker compose down会怎么样?
bash
knd@NightCode:~/dockertest/dockercompose_test/prj1$ sudo docker compose down 0.1s
✔ Container prj1-nginx-1 Removed 0.1s
✔ Network prj1_default Removed
knd@NightCode:~/dockertest/dockercompose_test/prj1$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
knd@NightCode:~/dockertest/dockercompose_test/prj1$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
825f3aba88a2 bridge bridge local
85f54d235a1c host host local
e3fb4a996c23 none null local
可以看到此项目创建的自定义网络与容器全部被删除了。
command
覆盖容器启动的默认命令。可以使用以下两种格式进行设置:
yaml
command: ["bundle", "exec", "thin", "-p", "3000"]
command: bundle exec thin -p 3000
tail -f /etc/hosts 命令的作用是: 实时监控 /etc/hosts 文件的变化 。
它会首先显示 /etc/hosts 文件的最后几行内容,然后会一直等待。如果系统中有任何程序修改并向这个文件追加了内容,这些新的内容会立刻被显示在你的终端上。
比如我要覆盖nginx的启动命令为tail -f /etc/hosts,可以这样编写文件:
yaml
services:
nginx:
image: nginx:1.29.4
command: tail -f /etc/hosts
#或者这样写
#command: ["tail","-f","/etc/hosts"]
可以看到nginx此时并没有运行起来:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker compose up -d
[+] up 2/2
✔ Network prj2_default Created 0.0s
✔ Container prj2-nginx-1 Created 0.1s
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker exec -it prj2-nginx-1 curl 127.0.0.1:80
curl: (7) Failed to connect to 127.0.0.1 port 80 after 0 ms: Could not connect to server
entrypoint
entrypoint 是 Docker 容器启动时执行的入口点指令,它定义了容器启动时运行的主要进程。
覆盖容器默认的entrypoint,这里我们只是简单的了解下,到后面我们学习了dockerfile才能有更进一步的认识。
yaml
entrypoint: /code/entrypoint.sh
也可以以下面的格式进行编写:
yaml
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-nonzts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit
我们来做一个演示:
yaml
services:
nginx:
image: nginx:1.29.4
entrypoint:
- tail
- -f
- /etc/hosts
这里的效果跟上面的command是一样的,都是替换启动命令,大家可以自行运行下看看。
environment
添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以
确保 YML 解析器不会将其转换为 True 或 False。
yaml
#map 语法
environment:
RACK_ENV: development
SHOW: "true"
USER_INPUT:
#数组语法
environment:
- RACK_ENV=development
- SHOW=true
- USER_INPUT
我们来演示以下:
yaml
name: webserver
services:
nginx:
image: nginx:1.29.4
environment:
- MYTESTBOOL="true"
- MYTESTINT=100
- MYTESTSTR="hello world"
运行效果如下:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker compose up -d
[+] up 2/2
✔ Network webserver_default Created 0.0s
✔ Container webserver-nginx-1 Created 0.1s
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker exec -it webserver-nginx-1 env | grep MYTEST
MYTESTSTR="hello world"
MYTESTBOOL="true"
MYTESTINT=100
networks
指定容器运行的网络:
配置容器网络:
yaml
services:
frontend:
image: awesome/webapp
networks:
- front-tier
- back-tier
monitoring:
image: awesome/monitoring
networks:
- admin
backend:
image: awesome/backend
networks:
back-tier:
aliases:
- database
admin:
aliases:
- mysql
networks:
front-tier:
back-tier:
admin:
对于上面这段配置的解释如下:
| 服务名称 | 镜像 (image) |
所属网络 (networks) |
说明 |
|---|---|---|---|
frontend |
awesome/webapp |
front-tier, back-tier |
负责前端展示,同时连接了面向用户的 front-tier 和面向后端的 back-tier。 |
monitoring |
awesome/monitoring |
admin |
负责监控,只连接到安全或管理专用的 admin 网络。 |
backend |
awesome/backend |
back-tier, admin |
作为后端服务,连接到: • back-tier (通过别名 database),供 frontend 访问。 • admin (通过别名 mysql),可能供 monitoring 或管理员访问。 |
配置网络驱动和子网信息
yaml
services:
frontend:
image: awesome/webapp
networks:
front-tier:
ipv4_address: 172.16.238.10
networks:
front-tier:
ipam:
driver: default
config:
- subnet: "172.16.238.0/24"
networks 定义(IPAM 配置)
- front-tier: 定义了一个名为 front-tier 的用户自定义网络。
- ipam (IP Address Management): 这是网络级别配置的关键部分,用于指定如何管理和分配网络中的 IP 地址。
- driver: default: 使用默认的 IPAM 驱动,通常适用于大多数桥接网络。
- config: 这是一个列表,包含 IP 地址池的配置。
- subnet: "172.16.238.0/24": 指定了该网络的 IP 地址范围。这意味着所有连接到 front-tier 网络的容器都将从 172.16.238.0 到 172.16.238.255 这个 C 类子网中获取 IP。
services 定义(静态 IP 分配)
- frontend: 定义了一个名为 frontend 的服务。
- networks: 服务连接到 front-tier 网络。
- front-tier :
ipv4_address: 172.16.238.10: 为 frontend 容器在 front-tier 网络中指定了一个固定的静态 IP 地址。
emm,需要注意在 Docker Compose 文件中定义网络时,如果不指定 ipam 配置,Docker 会使用其默认的网络管理策略。
我们下面基于上面的示例写一段自定义网络,配置其ip分配同时可以让一个容器通过别名访问另一个容器上的nginx服务:
yaml
name: webserver
services:
nginx:
image: nginx:1.29.4
networks:
mynet1:
ipv4_address: 192.168.0.2
aliases:
- mynginx
busybox:
image: busybox:latest
# 启动 sh,然后运行一个无限循环,让容器保持在运行状态
command: sh -c "while true; do sleep 3600; done"
networks:
mynet1:
ipv4_address: 192.168.0.3
aliases:
- mybusybox
networks:
mynet1:
ipam:
driver: default
config:
- subnet: 192.168.0.0/16
我们让他运行起来跑下看看,我不知道为什么我这个busybox没有curl命令,所以我换成了wget来做个演示:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker exec -it webserver-busybox-1 sh
/ # wget mynginx
Connecting to mynginx (192.168.0.2:80)
saving to 'index.html'
index.html 100% |************************************************************************************************| 615 0:00:00 ETA
'index.html' saved
/ # cat index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
可以看到是能够正常访问另一个容器里的nginx服务的,那我们去在手动启动一个busybox容器连接到此自定义网络ping一下上面的两个容器试试:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker run -itd --name b1 --network=webserver_mynet1 busybox
232bdf8f207489ea6cf774a1c8e290027a8104c3fe3f22407ca684eb1a3f4634
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker exec -it b1 ping mynginx
PING mynginx (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: seq=0 ttl=64 time=0.233 ms
64 bytes from 192.168.0.2: seq=1 ttl=64 time=0.063 ms
^C
--- mynginx ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.063/0.148/0.233 ms
knd@NightCode:~/dockertest/dockercompose_test/prj2$ sudo docker exec -it b1 ping mybusybox
PING mybusybox (192.168.0.3): 56 data bytes
64 bytes from 192.168.0.3: seq=0 ttl=64 time=0.067 ms
64 bytes from 192.168.0.3: seq=1 ttl=64 time=0.052 ms
^C
--- mybusybox ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.052/0.059/0.067 ms
可以看到都ping成功了!
volumes
将主机的数据卷或者文件挂载到容器里。
yaml
services:
# 短语法示例
db:
image: postgres:latest
volumes:
# 绑定挂载(Bind Mount):宿主机路径:容器路径
- "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
# 绑定挂载:宿主机路径:容器路径
- "/localhost/data:/var/lib/postgresql/data"
# 完整语法示例
backend:
image: awesome/backend
volumes:
# 命名卷(Named Volume)配置
- type: volume
source: db-data # 卷名称(在顶层 volumes 部分定义)
target: /data
volume:
nocopy: true # 避免从容器镜像内容初始化卷
# 绑定挂载(Bind Mount)配置
- type: bind
source: /var/run/postgres/postgres.sock
target: /var/run/postgres/postgres.sock
# 顶层 volumes 部分:定义命名卷
volumes:
db-data:
# 可以在这里添加 driver, driver_opts, external 等配置
这里就不再作演示了,不过需要提醒的是,注意到短语法哪里的/localhost/postgres.sock:/var/run/postgres/postgres.sock"了吗。目标路径 /var/run/postgres/postgres.sock 中的 .sock 后缀,明确指出这是一个 Unix Domain Socket 文件。
这种文件是操作系统用于同一机器上不同进程间通信(IPC)的特殊文件 ,而不是一个普通的数据目录。
在 Docker 的 绑定挂载(Bind Mount) 短语法中 (宿主机路径:容器路径):如果宿主机路径指向一个文件,那么挂载操作就是将该文件映射到容器路径下的一个文件。
还需要注意的是如果挂载的是主机路径且仅被单个服务使用,它可以作为服务定义的一部分声明。若要在多个服务之间重用一个卷,必须在 volumes 顶级元素中声明命名卷。
其他的内容可以在官方文档中看,因为大多数配置我们前面都说过,你像存储卷的名字,元信息设置,驱动设置这些。无非多的就是一个external属性,可以看官方文档的描述:
volume-external
ports
指定端口映射。以下格式都可以:
yaml
#完整语法
ports:
- target: 80
host_ip: 127.0.0.1
published: 8080
protocol: tcp
mode: host
我们对上面的配置进行下解析
| 字段 | 值 | 描述 |
|---|---|---|
target |
80 |
容器内部端口。 这是服务在 Docker 容器内部监听的端口(例如,容器内运行的 Web 服务器)。 |
published |
8080 |
宿主机暴露端口。 这是在宿主机上实际开放并监听的端口。外部流量将通过此端口访问容器服务。 |
host_ip |
127.0.0.01 |
宿主机 IP 地址。 指定宿主机上的哪个网络接口 IP 地址将监听 published 端口。127.0.0.1 表示仅在本地回环地址上监听,这意味着服务只能从宿主机本身(localhost)访问,不能从外部网络访问。 |
protocol |
tcp |
网络协议。 指定端口使用的协议,这里是 TCP。 |
mode |
host |
映射模式。 host 模式表示端口将通过宿主机的网络堆栈进行发布。注意: 在大多数情况下,如果只配置 target 和 published,默认模式是 ingress。但在这里显式设置 mode: host 强调了端口映射的方式。 |
不过我们一般用到的都是短语法,相当于run那里的-p:
yaml
#短语法
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
我们来做一个演示,仅作短语法的演示,长语法一般我们也使用不到,就是一个简单的暴露nginx容器的80端口来让外界访问:
yaml
name: webserver
services:
nginx:
image: nginx:1.29.4
ports:
- 8080:80
可以看到运行之后是可以正常访问的:

expose
expose 参数的目的是声明(Declare)服务在容器内部监听的端口,但不会将这些端口实际发布(Publish)到宿主机(Host machine)的网络接口上。
仅可以指定内部端口为参数:
yaml
expose:
- "3000"
- "8000"
他其实没干啥事情,只是声明说我容器内部服务监听的是expose指定的几个端口,很简单我们这里便不再演示。
build
指定为构建镜像上下文路径:
例如 webapp 服务,指定为从上下文路径 ./dir/Dockerfile 所构建的镜像:
yaml
version: "3.7"
services:
webapp:
build: ./dir
或者,作为具有在上下文指定的路径的对象,以及可选的 Dockerfile 和 args:
yaml
version: "3.7"
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
- context:上下文路径。
- dockerfile:指定构建镜像的 Dockerfile 文件名。
- args:添加构建参数,这是只能在构建过程中访问的环境变量。
- labels:设置构建镜像的标签。
这个我们后面学习了dockerfile在来进行详细认识,其实很简单。
depends_on
设置启动依赖关系:
比如说我有一个web服务,它由nginx与mysql协作运行,那么启动这个服务的时候,需要数据库先启动然后再启动nginx确保nginx能够连接上数据库以确保web的正常运行,那我们使用docker compose如何达到这种效果呢:
yaml
name: webserver
services:
nginx:
image: nginx:1.29.4
ports:
- 8080:80
depends_on:
- mysql
mysql:
image: mysql:8.0.44
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- ./mysql:/var/lib/mysql
但是,有的时候并不是说我数据库刚启动就能正常连接的,一般我们认为当mysql能够正常执行一条sql语句的时候,它才是健康的。此时才能够让我们的nginx连接到mysql数据库服务。那这种情况下我们就可以在docker compose中增加一个健康检查:
yaml
name: webserver
services:
nginx:
image: nginx:1.29.4
ports:
- 8080:80
depends_on:
mysql:
condition: service_healthy
mysql:
image: mysql:8.0.44
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- ./mysql:/var/lib/mysql
healthcheck:
test: mysql -u root -p123456 -e "SELECT 1"
interval: 10s
timeout: 5s
retries: 10
test表示健康检查执行的命令,也支持像我们前面command那样使用json格式进行书写。interval表示健康检查的间隔,timeout表示超时时间,retries表示重试的次数。而depends_on中的condition常见的有两个,一个是service_started表示依赖服务正常启动后即可进行此服务的运行。一个是service_healthy表示只有当依赖服务能够通过healthy时才能启动当前服务。我们来运行下看看:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj1$ sudo docker compose up -d
[+] up 2/3
✔ Network webserver_default Created 0.0s
⠴ Container webserver-mysql-1 Waiting 100.7s
✔ Container webserver-nginx-1 Created 0.1s
dependency failed to start: container webserver-mysql-1 is unhealthy
这是启动失败的情况,我把test内的密码输错了即可看到。正常启动的情况应该是这样的:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj1$
✔ Container webserver-mysql-1 Healthy 10.8s
✔ Container webserver-nginx-1 Created 0.1s
...
222e1fac14f7 mysql:8.0.44 "docker-entrypoint.s..." 33 seconds ago Up 33 seconds (healthy) 3306/tcp, 33060/tcp webserver-mysql-1
而且使用docker ps 时也会看到mysql容器后面多了一个(healthy)的标识。
env_file
从文件添加环境变量。可以是单个值或列表的多个值。
yaml
env_file: ./test.env
yaml
env_file:
- ./test.env
- ./test2.env
- ./test3.env
我们来试下,我们在列表的三个文件中分别加入MYTEST1=1,MYTEST2=2,MYTEST3=3这三个环境变量然后让nginx跑起来:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj3$ sudo docker exec -it webserver-nginx-1 env | grep MYTEST
MYTEST1=1
MYTEST2=2
MYTEST3=3
可以看到它成功的从三个环境变量配置文件中读取了配置并且写入了新容器的环境变量中。
2.3 docker compose常见命令
| 命令 | 功能 |
|---|---|
| docker compose build | 构建服务 |
| docker compose config | 规范的格式来显示服务配置 |
| docker compose cp | 在本地系统和服务容器直接拷贝文件 |
| docker compose create | 创建服务的容器 |
| docker compose down | 停止所有容器,并删除容器 |
| docker compose events | 从服务器获取实时事件 |
| docker compose exec | 在容器中执行命令 |
| docker compose images | 列出所有容器使用的镜像 |
| docker compose kill | 强制停止服务的容器 |
| docker compose logs | 显示日志 |
| docker compose ls | 显示所有项目 |
| docker compose pause | 暂停服务 |
| docker compose port | 列出所有的端口映射 |
| docker compose ps | 该命令可以列出项目中目前的所有容器 |
| docker compose pull | 拉取服务镜像 |
| docker compose push | 推送服务镜像 |
| docker compose restart | 重启或者重启某个服务 |
| docker compose rm | 删除服务停止的容器 |
| docker compose run | 在指定服务器上执行相关的命令 |
| docker compose start | 启动当前停止的某个容器 |
| docker compose stop | 停止当前运行的某个容器 |
| docker compose top | 显示运行的进程 |
| docker compose unpause | 恢复服务 |
| docker compose up | up 命令会构建、(重新)创建、启动、链接一个服务相关的容器。默认情况下如果容器已经存在,将会停止并尝试重新创建他们,并使用之前挂载的卷。--no-recreate 参数可以让容器不被停止或者重新创建,-d 表示后台运行 |
| docker compose version | 查看版本 |
这部分我们就不再细致入微的一个一个认识了。我们专挑经常使用的几个选项和命令介绍,其他的大家如果有兴趣可以结合官方文档与ai辅助来进行学习:
命令格式
对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器。如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响。
docker-compose 命令的基本的使用格式为:
bash
docker compose [OPTIONS] COMMAND [ARGS...]
- -f, --file 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定
- -p, --project-name 指定项目名称,默认将使用所在目录名称作为项目名
比如我现在处于一个一级目录,但是我的yaml文件在当前目录下的一个二级目录内,并且我不想去用默认给的前缀项目名称,此时就可以-f与-p同时进行使用:
bash
knd@NightCode:~/dockertest/dockercompose_test$ sudo docker compose -f ./prj3/docker-compose.yml -p mytest up -d
knd@NightCode:~/dockertest/dockercompose_test$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0.0s
e67540a22dcf nginx:1.29.4 "/docker-entrypoint...." 5 seconds ago Up 4 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mytest-nginx-1s
docker compose up
该命令的作用十分强大,它会尝试自动完成包括构建镜像、(重新)创建服务、启动服务并关联服务相关容器的一系列操作,可以直接通过该命令来启动一个项目。
bash
docker compose up [options] [SERVICE...]
- -d 在后台运行服务容器, 推荐在生产环境下使用该选项
- --force-recreate 强制重新创建容器,不能与 --no-recreate 同时使用
- --no-recreate 如果容器已经存在了,则不重新创建,不能与 --forcerecreate 同时使用
我们上面不是已经创建了一个nginx容器,我们这里拿它进行后面两个选项的开刀演示:
bash
knd@NightCode:~/dockertest/dockercompose_test$ sudo docker compose -f ./prj3/docker-compose.yml -p mytest2 up -d --no-recreate
[+] up 2/2
✔ Network mytest2_default Created 0.0s
✔ Container mytest2-nginx-1 Created 0.1s
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint mytest2-nginx-1 (e9b66a456651816337b265c6c4d0d71a354ccc8884e2127734a27c2a52494519): Bind for 0.0.0.0:8080 failed: port is already allocated
如果你重命名了它是不会认为这个项目之前已经存在了。
bash
knd@NightCode:~/dockertest/dockercompose_test$ sudo docker compose -f ./prj3/docker-compose.yml -p mytest up -d --no-recreate
knd@NightCode:~/dockertest/dockercompose_test$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e67540a22dcf nginx:1.29.4 "/docker-entrypoint...." 4 minutes ago Up 4 minutes 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mytest-nginx-1
因为我们的容器之前已经存在了,所以它这里不会再进行重新创建。
bash
knd@NightCode:~/dockertest/dockercompose_test$ sudo docker compose -f ./prj3/docker-compose.yml -p mytest up -d --force-recreate
[+] up 1/1
✔ Container mytest-nginx-1 Recreated 0.3s
加上--force-recreate选项即可让我们已经创建好的容器重新创建。
docker compose down
停止所有容器,并删除容器和网络
bash
docker compose down [options] [SERVICE...]
- -v, --volumes 删除容器同时删除目录映射
我们之前进行volumes的实验时,发现它down的时候并不会将服务创建时创建的存储卷也一并删除,其实加上-v选项即可:
yaml
name: webserver
services:
nginx:
image: nginx:1.29.4
ports:
- 8080:80
volumes:
- mytestvolume:/usr/share/nginx/html
volumes:
mytestvolume:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj3$ sudo docker compose down -v
[+] down 3/3 webserver-nginx-1 Created 0.1s
✔ Container webserver-nginx-1 Removed 0.2s
knd@NightCode:~/dockertest/dockercompose_test/prj3$ sudo docker volume ls 0.0s
DRIVER VOLUME NAMEdefault Removing 0.0s
可以看到此时把我们的存储卷也一并带走了。
docker compose run
该命令可以在指定服务容器上执行相关的命令Shell,官方推荐最好执行的是一次性的命令。
bash
#例如:启动一个 ubuntu 服务容器,并执行 ping docker.com 命令
docker compose run ubuntu ping docker.com
bash
docker compose run [options] SERVICE [COMMAND] [ARGS...]
- -d 后台运行容器(容器会在执行完命令后停止)
- --name NAME 为容器指定一个名字
- --entrypoint CMD 覆盖默认的容器启动指令
- -e KEY=VAL 设置环境变量值,可多次使用选项来设置多个环境变量
- -u, --user="" 指定运行容器的用户名或者 uid
- --rm 运行命令后自动删除容器
- -p, --publish=[] 映射容器端口到本地主机
这里可以类比我们之前在容器命令部分认识的docker run与docker exec。不过这里后面需要跟上的是服务名称,而容器那里则是要跟上一个镜像名称与标签。我们这里用我们之前的busybox镜像随便ping一个网址试试:
yaml
name: webserver
services:
nginx:
image: nginx:1.29.4
ports:
- 8080:80
volumes:
- mytestvolume:/usr/share/nginx/html
busybox:
image: busybox:latest
volumes:
mytestvolume:
bash
knd@NightCode:~/dockertest/dockercompose_test/prj3$ sudo docker compose run busybox ping qq.com
Container webserver-busybox-run-ffdeaaac6d57 Creating
Container webserver-busybox-run-ffdeaaac6d57 Created
PING qq.com (112.60.14.252): 56 data bytes
64 bytes from 112.60.14.252: seq=0 ttl=250 time=29.682 ms
64 bytes from 112.60.14.252: seq=1 ttl=250 time=29.799 ms
64 bytes from 112.60.14.252: seq=2 ttl=250 time=29.599 ms
64 bytes from 112.60.14.252: seq=3 ttl=250 time=29.685 ms
^C
--- qq.com ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 29.599/29.691/29.799 ms
knd@NightCode:~/dockertest/dockercompose_test/prj3$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
905cfeee4de0 busybox:latest "ping qq.com" 11 seconds ago Exited (0) 8 seconds ago webserver-busybox-run-ffdeaaac6d57
可以看到它ping成功了并正常退出了。所以说docker compose这里大多数命令都和前面我们容器部分的使用方式大差不差,大家自己去认识也会很简单。
三.使用docker compose搭建一个wordpress站点
我们先来看看wordpress官方镜像下面的叙述:
The WORDPRESS_DB_NAME needs to already exist on the given MySQL server; it will not be created by the wordpress container.
它说的是如果我们想要去构建一个wordpress站点使用docker,那么前提是我们需要有一个mysql的数据库服务。ok,那么这里我们就可以结合上面我们学习过的知识来进行一个wordpress站点的搭建:
yaml
services:
wordpress:
image: wordpress:latest
restart: always
ports:
- 8080:80
depends_on:
mysql:
condition: service_healthy
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: "114514@ahhh"
WORDPRESS_DB_NAME: wordpress
volumes:
- ./wordpress:/var/www/html
networks:
- wordpress
mysql:
image: mysql:8.0.44
restart: always
environment:
MYSQL_ROOT_PASSWORD: "114514@1919180"
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: "114514@ahhh"
volumes:
- ./mysql:/var/lib/mysql
healthcheck:
test: mysql -u root -p114514@1919180 -e "SELECT 1"
interval: 10s
timeout: 5s
retries: 10
networks:
- wordpress
networks:
wordpress:
driver: bridge
ok,配置文件编写完毕,此时我们可以直接用dokcer compose up -d启动我们的服务了,我们来访问下我们自己服务器的8080端口看看:

启动成功!
接下来与图形化界面进行交互即可进入到如下界面了:

我们随便写一篇文章看看效果:

当然这也只是最简单的wordpress站点。如果想要更加好看些,这里博主推荐一个b站大佬的主题:
Kizumi:优雅的二次元WP博客主题,开源!
这时大佬提供的主题文档地址(视频底部简介就有链接):
文档地址
我自己的博客网站就是使用大佬的主题进行搭建的,效果如下:

也可以访问如下网址进行其他细节的查看,我是很喜欢大佬的这个主题的哈哈。
NightBlog-dddebug到厌倦