Docker 命令 之 docker compose

摘要

docker compose 是什么?

  • Docker Compose 用一份 YAML 描述多个服务、网络和卷。docker compose up 按这份文件创建并启动它们。同一网络里的服务用服务名互相访问。

  • 换环境时改文件里的变量或换一份 env_file,服务定义可以保持不动。

  • 把同一份文件交给 Swarm 时,build、depends_on 由 docker compose up 使用,deploy 由 docker stack deploy 使用。对照表见 Docker Swarm 之 栈(Stack)。

docker compose 安装

  • Docker Engine 的安装见 Linux 安装 Docker,其中已经包含 docker-compose-plugin。命令是 docker compose。

  • 引擎已经在、插件不在时,单独安装插件后看版本:

1
2
sudo dnf install docker-compose-plugin -y
docker compose version

docker compose 命令

命令 中文说明 示例
attach 连接到服务的运行中容器的标准输入、输出和错误流 docker compose attach web
build 构建或重新构建服务 docker compose build
config 解析并标准化 Compose 文件 docker compose config
cp 在服务容器与本地文件系统之间复制文件/文件夹 docker compose cp web:/app/file.txt ./file.txt
create 为服务创建容器,但不启动 docker compose create
down 停止并移除容器、网络等资源 docker compose down
events 实时接收容器事件 docker compose events
exec 在运行中的容器中执行命令 docker compose exec web ls /app
images 列出已创建容器所使用的镜像 docker compose images
kill 强制停止服务容器 docker compose kill
logs 查看服务容器的日志输出 docker compose logs
ls 列出当前运行的 Compose 项目 docker compose ls
pause 暂停服务容器 docker compose pause
port 显示某端口映射的公网地址 docker compose port web 80
ps 列出服务的容器 docker compose ps
pull 拉取服务使用的镜像 docker compose pull
push 推送服务镜像到仓库 docker compose push
restart 重启服务容器 docker compose restart
rm 移除已停止的服务容器 docker compose rm
run 在服务上运行一次性命令 docker compose run web echo Hello
scale 扩展服务实例数量 docker compose up --scale web=3
start 启动已存在但已停止的服务容器 docker compose start
stats 实时显示容器资源使用情况 docker compose stats
stop 停止运行中的服务容器 docker compose stop
top 显示容器内的运行进程 docker compose top
unpause 取消暂停服务容器 docker compose unpause
up 创建并启动服务容器 docker compose up
version 显示 Docker Compose 版本信息 docker compose version
wait 阻塞直到第一个服务容器停止 docker compose wait
watch 监听服务构建上下文变更并重新构建/刷新容器 docker compose watch

docker compose 常用命令

  • 启动与关闭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 启动并运行,默认使用当前目录的 docker-compose.yml 文件
docker compose up
# 后台运行
docker compose up -d
# 指定compose文件
docker compose -f docker-compose.yml up -d
# 启动多个 compose 文件,会先加载 compose1.yml 文件,再加载 compose2.yml 文件,然后将两个配置文件合并成一个最终配置,并基于合并后的配置启动所有服务
# 如果两个 compose 文件有相同的 service 名称,那么 compose2.yml(后加载的) 文件中的配置会 覆盖/追加 compose1.yml(先加载的) 文件中的配置,即相同配置项覆盖,不同配置项追加
# 重要理解:不是“两个文件分别启动”,而是“文件合并后启动”
docker-compose -f compose1.yml -f compose2.yml up -d

# 如果 compose 文件中定义了多个 service,那么 docker compose up 命令会启动所有 service
# 如果只想启动时指定service,可以使用如下命令
docker compose up service_name
# 如果想启动多个service,可以使用如下命令
docker compose up service_name1 service_name2

# 启动时重建服务,当修改了 compose 文件时
docker compose up --build
# 停止service
docker compose stop
# 强制停止service,当 stop 命令无法停止时
docker compose kill
# 重启service
docker compose restart
# 删除service,-s 参数表示删除前先停止容器
docker compose rm -s
# 停止并删除service,同时删除网络,但不会删除卷
docker compose down
  • 监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 列出当前运行的 Compose 项目
docker compose ls
# 查看service状态,-a 显示所有service
docker compose ps -a
# 解析并标准化 compose 文件,这个命令可以检查 docker-compose.yml 文件语法是否正确,但不保证逻辑正确
docker compose config
# 查看使用的镜像
docker compose images
# 查看进程
docker compose top
# 查看service资源使用情况
docker compose stats
# 查看service日志,-f 表示持续跟踪
docker compose logs -f
# 查看指定service的日志
docker compose logs -f service_name
# 进入指定的service容器
docker compose exec service_name bash
  • 升级镜像

1
2
3
4
5
6
# 先停止所有service
docker compose down
# 拉取最新镜像
docker compose pull
# 启动service
docker compose up -d --build

docker compose 默认文件名

  • 默认会按下面顺序查找,只要当前目录中存在其中一个,就会自动使用。

1
2
3
4
docker-compose.yml
docker-compose.yaml
compose.yml
compose.yaml

docker-compose.yml 的语法

  • 一份文件里常用到的键。每个键的说明在后面的同名标题下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# version 已过时。新版 Docker 按 Compose Specification 解析,写上只会告警
name: project_name # 项目名,默认是本文件所在目录名
services:
servicename: # 服务名:小写字母、数字、下划线和中划线,以字母或数字开头
image: # 镜像。同时写了 build 时,这也是构建结果的名字
build: # 用 Dockerfile 构建。指令见 Dockerfile 一篇
pull_policy: # 启动时拉镜像、用本地镜像,还是重新构建
container_name: # 固定容器名。写了就不能把副本数扩成多个
command: # 覆盖镜像的 CMD。只写参数时,交给镜像的 ENTRYPOINT
entrypoint: # 覆盖镜像的 ENTRYPOINT
user: # 用户,或 用户:组
working_dir:
environment:
env_file:
ports: # 映射到宿主机
expose: # 只在 Compose 网络内声明
volumes:
networks:
network_mode: # 写了它就不能再写 networks
extra_hosts:
dns:
depends_on: # docker compose up 用来安排启动顺序。docker stack deploy 忽略它
restart: # 容器自己退出后的策略。Stack 改用 deploy.restart_policy
healthcheck:
cpus:
mem_limit:
read_only:
tmpfs:
cap_drop:
security_opt:
logging:
profiles: # 只有命令行带上同名 --profile 才启动
develop: # 配合 docker compose watch
volumes: # 命名卷,供上面的 services.*.volumes 引用
networks:

volumes

  • 卷是由容器引擎实现的持久数据存储。Compose 为服务提供了一种中立的挂载卷的方式,并通过配置参数将卷分配给基础架构。顶级volumes声明允许您配置可在多个服务之间重复使用的命名卷。

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
backend:
image: example/database
volumes: # 挂载卷映射
- db-data:/etc/data # 挂载到容器的/etc/data目录

backup:
image: backup-service
volumes:
- db-data:/var/lib/backup/data # 一个卷可以被多个服务使用

volumes: # 存储卷配置
db-data: # 创建一个名为db-data的卷,实际的网络名称是 容器组名称_这里的名称

driver

  • driver: 卷类型,默认为local,指定应使用哪个卷驱动程序。如果该驱动程序不可用,Compose 将返回错误并且不会部署该应用程序。

1
2
3
4
volumes:
db-data: # 声明一个名为db-data的卷
driver: local # 指定卷类型,这个是默认值,可以不配置
db-data2: # 声明一个名为db-data2的卷,这是最简单的 volumes 配置

driver_opts

  • driver_opts: 卷类型参数,指定要传递给此卷驱动程序的选项列表(以键值对的形式)。这些选项与驱动程序相关。

1
2
3
4
5
6
volumes:
db-data:
driver_opts: # 卷类型参数,指定要传递给此卷驱动程序的选项列表(以键值对的形式)
type: "nfs" # 卷类型,指定应使用哪个卷驱动程序,这里是nfs
o: "addr=10.40.0.199,nolock,soft,rw" # nfs参数,addr为nfs服务器地址,nolock为不锁定文件,soft为软链接,rw为读写权限
device: ":/docker/example" # nfs挂载路径

external

  • external: 卷是否为外部卷,默认为false

1
2
3
volumes:
db-data:
external: true # true 表示不会创建,而是使用已存在的,即会去volumes中查找(docker volume ls) 容器组名称_da-data ,默认为false

name

  • name: 卷的名称,默认为 容器组名称_声明的名称

1
2
3
4
volumes:
db-data:
name: db-data # 创建一个名为db-data的卷,实际的卷名称就是 db-data,不会再加上容器组名称前缀
external: true # name 属性经常与 external: true 一起使用

labels

  • labels: 用于向卷添加元数据,可以添加任意的键值对

1
2
3
4
5
6
volumes:
db-data:
labels:
com.example.description: "Database volume"
com.example.department: "IT/Ops"
com.example.label-with-empty-value: ""

networks

  • 网络使服务能够相互通信。默认情况下,Compose 会为您的应用设置单个网络。服务的每个容器都会加入默认网络,并且该网络上的其他容器都可以访问,并且可以通过服务名称发现。顶级networks元素允许您配置可在多个服务之间重复使用的命名网络。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
frontend:
image: example/webapp
networks: # 网络映射
- front-tier # 加入front-tier网络
- back-tier
db:
image: postgres
networks:
- backend

networks: # 网络配置
front-tier: # 创建一个名为front-tier的网络,实际的网络名称是 容器组名称_front-tier
back-tier:
  • 如果 Compose 文件未显式声明网络,Compose 将使用隐式default网络。

1
2
3
4
5
6
7
8
9
10
11
12
services:
some-service:
image: foo

# 这个例子实际上等同于:
services:
some-service:
image: foo
networks:
default: {}
networks:
default: {}

driver

  • driver: 网络类型,默认为bridge

1
2
3
networks:
gitea:
driver: bridge

driver_opts

  • driver_opts: 网络类型参数,指定要传递给此网络驱动程序的选项列表(以键值对的形式)。这些选项与驱动程序相关。

1
2
3
4
5
networks:
frontend:
driver: bridge
driver_opts:
com.docker.network.bridge.host_binding_ipv4: "127.0.0.1" # 设置容器端口绑定到主机的哪个 IP(如 "127.0.0.1",绑定到本地)

driver_opts 常见配置项(针对 bridge 网络驱动)

选项键名(driver_opts) 说明
com.docker.network.bridge.name 指定桥接网络的名称(默认是随机生成,如 br-xxxxx)
com.docker.network.bridge.enable_icc 是否允许容器之间的通信(true 或 false)
com.docker.network.bridge.enable_ip_masquerade 是否启用 IP 假冒(NAT,通常用于外网访问)
com.docker.network.bridge.host_binding_ipv4 设置容器端口绑定到主机的哪个 IP(如 "127.0.0.1",绑定到本地)
com.docker.network.bridge.default_bridge 是否将该网络设置为默认 bridge 网络(true 或 false)
com.docker.network.driver.mtu 设置网络的最大传输单元(MTU,例如 "1500")
com.docker.network.bridge.allow_non_default_bridge 是否允许容器加入非默认的 bridge 网络(较少使用)

attachable

  • attachable: 如果为true,则允许将其它独立容器也加入到此网络。默认值为false。如果独立容器连接到此网络,它可以与同样连接到此网络的服务和其他独立容器进行通信。

1
2
3
networks:
gitea:
attachable: true

external

  • external: true 表示不会创建新的网络,回去networks中查找(docker network ls),默认为false

1
2
3
networks:
gitea:
external: true

name

  • name: 网络名称,不会再加上容器组名称前缀

1
2
3
4
networks:
gitea:
name: gitea
external: true # name 属性经常与 external: true 一起使用

labels

  • labels: 用于向网络添加元数据,可以添加任意的键值对

1
2
3
4
5
6
networks:
mynet1:
labels:
com.example.description: "Financial transaction network"
com.example.department: "Finance"
com.example.label-with-empty-value: ""

internal

  • internal: 默认情况下,Compose 提供网络的外部连接。internal当设置为 时true,可让您创建与外部隔离的网络。

1
2
3
networks:
gitea:
internal: true

services

  • 服务是应用程序中计算资源的抽象定义,可以独立于其他组件进行扩展或替换。服务由一组容器支持,由平台根据复制要求和布局约束运行。由于服务由容器支持,因此它们由 Docker 镜像和一组运行时参数定义。服务中的所有容器都使用这些参数以相同的方式创建。

  • service 包含的属性非常多,具体请参考services顶级元素,这里只介绍比较常用的属性,

  • 这里以Gitea的docker-compose.yml为例

Gitea 是一种轻松、自托管的一体化软件开发服务。它包括 Git 托管、代码审查、团队协作、包注册表和 CI/CD。它类似于 GitHub、Bitbucket 和 GitLab。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# version: '3.8' # 配置文件版本,已过时,配置上会告警但不会报错
# name: gitea # 容器组名称,默认使用所在目录的名称,不推荐使用
networks: # 网络配置
gitea: # 创建一个名为gitea的网络,实际的网络名称是 gitea_gitea,即 容器组名称_这里的名称
external: false # 如果为true,则表示此网络不会由compose创建,而是使用已有的网络,默认为false
driver: bridge # 网络类型,默认为bridge

volumes: # 存储卷配置
gitea: # 创建一个名为gitea的存储卷,实际的卷名称是 gitea_gitea,即 容器组名称_这里的名称
driver: local # 存储卷类型,默认为local

services: # 服务配置,这里可以定义一组容器
server: # 定义一个名为server的服务,注意这个不是容器名称
# build: . # 构建镜像,使用当前目录下的Dockerfile
image: gitea/gitea:latest # 镜像名称
# container_name: gitea # 容器名称,默认为 “容器组名称-服务名称-索引”,不推荐配置,因为 水平扩展(--scale) 时,容器名称不能重复
environment: # 定义环境变量
- USER_UID=1000 # key=value
- USER_GID=1000
- DB_TYPE=mysql
- DB_HOST=db:3306 # 这里配置的 db 就是 下面的服务名称,相同 network 下的服务名称,docker compose会自动解析为容器的ip地址
- DB_NAME=gitea
- DB_USER=gitea
- DB_PASSWD=gitea
# env_file: .gitea.env # 从 .gitea.env 文件读取环境变量,生产环境更推荐
restart: always # 容器启动时,自动重启
networks: # 网络关联
- gitea # 网络名称,就是上面创建的gitea网络
volumes: # 数据卷关联
- gitea:/data # volume映射,数据卷名称:/容器路径
- /etc/timezone:/etc/timezone:ro # 路径映射,宿主机路径:/容器路径:读写权限
- /etc/localtime:/etc/localtime:ro
ports: # 端口映射
- "3000:3000" # 宿主机端口:容器端口
depends_on: # 启动依赖,就是依赖的服务启动后才能启动本服务
db: # 启动db服务
condition: service_healthy # 服务通过健康检查,也可以配置为 service_started:服务启动,这个是默认值

db: # 数据库服务
image: mysql:8 # 镜像
environment: # 环境变量
- MYSQL_ROOT_PASSWORD=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=gitea
- MYSQL_DATABASE=gitea
restart: always # 启动策略
networks: # 网络映射
- gitea # 映射到gitea网络
volumes: # 卷映射
- ./mysql:/var/lib/mysql # 宿主机路径:/容器路径,这里宿主机支持相对路径
healthcheck: # 健康检查
test: ["CMD-SHELL", "mysql -u root -pgitea", "-e 'SELECT 1;'"] # 执行命令,如果返回0,则健康检查通过,这里不支持上面的环境变量,test只支持 CMD-SHELL 和 CMD
interval: 10s # 健康检查间隔
timeout: 5s # 健康检查超时时间
retries: 3 # 健康检查重试次数

build

  • build: 构建镜像

1
2
3
4
services:
server:
build: . # Dockerfile的目录,“.” 表示使用当前目录下的Dockerfile
image: example/webapp # 镜像名称,如果有build,则该名称就是build后的镜像名称,如果没有build,则就会从远程仓库拉取
1
2
3
4
5
6
7
8
9
10
11
12
13
services:
server:
build:
context: ./webapp # Dockerfile的目录,默认是当前目录
dockerfile: Dockerfile # 构建镜像的Dockerfile名称,默认是Dockerfile
platforms: # 构建镜像的架构
- linux/amd64 # 构建镜像的架构,默认是当前架构
args: # 构建镜像的参数
- FOO=bar
labels: # 构建镜像的标签
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
  • build 里还常用这些字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
services:
server:
image: example/webapp
build:
context: ./webapp
dockerfile: Dockerfile
target: prod # 多阶段 Dockerfile 里要构建的阶段名
pull: true # 重新拉取 Dockerfile 中 FROM 的基础镜像,本机已经有也拉
no_cache: true # 不使用构建缓存,Dockerfile 里的每一层都重新执行
network: host # 构建阶段 RUN 使用的网络:default、host、none。这是 docker build 的网络,不是顶层 networks 里的名字
ssh:
- default # 把本机 SSH agent 提供给构建,Dockerfile 里用 RUN --mount=type=ssh
cache_from: # 从这些位置读取构建缓存。构建器不认识的类型会被忽略
- type=registry,ref=example/webapp:cache
cache_to: # 把本次构建缓存导出到这些位置
- type=local,dest=./cache
additional_contexts: # 额外的命名构建上下文
resources: ./resources
tags: # 除服务的 image 之外,再给构建结果打的标签
- example/webapp:prod
secrets: # 只有构建过程能读到,对应下面的顶层 secrets
- server-certificate
secrets:
server-certificate:
file: ./server.cert

image

  • image: 容器使用的镜像。写法是 [仓库地址/][命名空间/]名字[:标签|@摘要]。

1
2
3
4
5
6
services:
server:
image: redis # 官方库,标签省略时是 latest
# image: redis:5
# image: redis@sha256:0ed5d5928d4737458944eb604cc8509e245c3e19d02ad83935398bc4b991aac7
# image: my_private.registry:5000/redis # 私有仓库要带地址和端口
  • 只写 build、不写 image 时,Compose 会构建镜像,但 docker compose push 会跳过这个服务并给出警告。两个都写、又没有 pull_policy 时,Compose 先按 image 拉取;仓库和本机缓存都没有,再按 build 构建,构建结果使用 image 这个名字。拉取策略见后面的 pull_policy。

container_name

  • container_name: 固定容器名。不写时名字是「项目名-服务名-序号」。

1
2
3
4
services:
server:
image: nginx
container_name: gitea # 须匹配 [a-zA-Z0-9][a-zA-Z0-9_.-]+
  • 写了 container_name 的服务只能有一个容器。再执行 --scale,或把后面的 scale 设成大于 1,Compose 会报错。

command

  • command: 覆盖容器映像声明的默认命令

1
2
3
4
services:
server:
command: ["python", "app.py"]
image: example/webapp

entrypoint

  • entrypoint: 声明服务容器的默认入口点,这覆盖了服务Dockerfile中的ENTRYPOINT指令。

1
2
3
4
5
6
7
8
9
10
11
12
services:
server:
image: example/webapp
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit
# 如果值为null,则使用图像的默认入口点。 entrypoint: null
# 如果值是 [](空列表)或 ''(空字符串),图像声明的默认入口点被忽略,或者换句话说,被覆盖为空。 entrypoint: []

depends_on

  • depends_on: 服务启动依赖,就是依赖的服务启动后才能启动本服务

1
2
3
4
5
6
7
8
9
10
services:
web:
build: .
depends_on:
- db # 短语法
- redis
redis:
image: redis
db:
image: postgres
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
services:
web:
build: .
depends_on:
db: # 长语法
condition: service_healthy # 满足的条件
restart: true # 当设置为true,Compose在更新依赖服务后重新启动此服务。
redis:
condition: service_started
required: false # Compose 2.20.0 起。false 时这个依赖没起来只警告,默认 true
redis:
image: redis
db:
image: postgres

## condition:设置依赖性被视为满足的条件
# service_started:相当于之前描述的简短语法
# service_healthy:指定在启动依赖服务之前,依赖预期为“健康”(如healthcheck所示)。
# service_completed_successfully:指定在启动依赖服务之前,依赖项预计将运行到成功完成。
# required:false 时依赖服务没启动只给出警告,默认 true。Compose 2.20.0 起。
# restart:true 时,Compose 更新了依赖服务之后,会重启当前服务。只针对 Compose 发起的更新,容器自己退出后的重启仍由 restart 策略决定。Compose 2.17.0 起。

environment

  • environment: 定义环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
server:
image: example/webapp
environment:
- FOO=bar
- BAZ=qux
# 或者
services:
server:
image: example/webapp
environment:
FOO: bar
BAZ: qux

env_file

  • env_file: 用于指定一个或多个包含要传递到容器的环境变量的文件。

1
2
3
4
5
6
services:
server:
image: example/webapp
env_file:
- ./a.env # 列表中的文件是从上到下处理的。对于两个环境文件中指定的相同变量,列表中最后一个文件的值是有效的。
- ./b.env
1
2
3
4
5
6
7
8
9
10
services:
server:
image: example/webapp
env_file:
- path: ./default.env
required: true # default
- path: ./override.env
required: false # 当required设置为false且.env文件缺失时,Compose会忽略
- path: ./raw.env
format: raw # 按原文传入。值里的 $ 和引号不再做变量替换
  • 同一个变量同时出现在 env_file 和 environment 里时,用 environment 的值。environment 里只写键、不写值,表示从当前执行 Compose 的环境里取;那里也没有这个变量时,容器里不会留下它。

restart

  • restart: 定义平台在容器终止时适用的策略

1
2
3
4
5
6
7
8
services:
server:
image: example/webapp
restart: "no" # 默认重启策略。在任何情况下,它都不会重新启动容器。
# restart: always # 策略总是重新启动容器,直到它被移除。
# restart: on-failure # 如果退出代码表明错误,策略将重新启动容器。
# restart: on-failure:3 # 如果退出代码表明错误,策略将重新启动容器。但仅尝试重启3次。
# restart: unless-stopped # 无论退出代码如何,策略都会重新启动容器,但当服务停止或删除时,策略会停止重新启动。

healthcheck

  • healthcheck: 健康检查。

1
2
3
4
5
6
7
8
9
10
services:
server:
image: example/webapp
healthcheck: # 健康检查
test: ["CMD", "curl", "-f", "http://localhost"] # 监控检查时执行的命令
interval: 1m30s # 健康检查的间隔,默认值为 30s
timeout: 10s # 健康检查的超时时间,默认值为 30s
retries: 3 # 健康检查的尝试次数,默认值为 3
start_period: 40s # 启动宽限期:在此期间,失败不会计入重试次数(仅用于判断服务是否启动完毕)
start_interval: 5s # 启动宽限期内检查的频率,本示例为在前 40 秒内每 5 秒检查一次

test定义Compose运行的命令来检查容器运行状况。它可以是字符串,也可以是列表。如果是列表,第一个项目必须是NONE、CMD或CMD-SHELL。如果它是一个字符串,它等同于指定CMD-SHELL后跟该字符串。

1
2
3
4
test: ["CMD", "curl", "-f", "http://localhost"]
# 使用CMD-SHELL运行配置为字符串的命令,使用容器的默认外壳(Linux的/bin/sh)。以下两种形式是等价的
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
test: curl -f https://localhost || exit 1

test 中的 CMD 和 CMD-SHELL 是两种不同的执行方式,它们的主要区别在于:

项目 CMD CMD-SHELL
✅ 用途 直接执行命令(不通过 shell) 通过 shell(如 /bin/sh -c)执行命令
🧾 写法格式 ["CMD", "executable", "arg1", "arg2"] ["CMD-SHELL", "command string"]
🔧 是否使用 shell 否 是
🧠 是否支持 shell 语法 ❌ 否
(不能使用 &&、 ||、\$VAR 等)
✅ 是
(支持管道、重定向、变量、命令组合)
🛡️ 安全性/可移植性 ✅ 更安全,执行更明确 ⚠ 依赖容器中存在 shell(如 /bin/sh)
⚙️ 执行效率 ✅ 稍快,因无需 shell 解析 ⚠ 稍慢,需通过 shell 启动
📦 推荐使用场景 - 简单健康检查命令
- 安全环境
- 精简镜像
- 需要使用逻辑控制(||, &&)
- 复杂检查逻辑
📌 示例 ["CMD", "curl", "-f", "http://localhost"] ["CMD-SHELL", "curl -f http\://localhost || exit 1"]
  • 关掉镜像自带的健康检查,用 disable: true,或把 test 设为 NONE。

1
2
3
4
5
6
services:
server:
image: example/webapp
healthcheck:
disable: true
# test: ["NONE"]

volumes

  • volumes: 挂载数据卷。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 长语法格式
services:
backend:
image: example/backend
volumes:
- type: volume # 安装类型。可以是是volume、bind、tmpfs、image、npipe、cluster
source: db-data # 挂载的源、绑定挂载的主机上的路径、映像挂载的Docker映像引用或顶层volumes键中定义的卷名称。不适用于tmpfs支架。
target: /data # 容器中装载卷的路径。
volume: # 配置其他卷选项
nocopy: true # 在创建卷时禁用从容器复制数据的标志,默认值为false。
subpath: sub # 挂载卷的子目录。即 db-data/sub
- type: bind # bind 表示挂载主机上的路径
source: /var/run/postgres/postgres.sock
target: /var/run/postgres/postgres.sock

volumes: # 声明数据卷
db-data:

######################################################################################

# 短语法格式
services:
backend:
image: example/backend
volumes:
- db-data:/data # 这种语法不支持 subpath 和 nocopy
- /var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock

volumes:
db-data:
  • 短语法是 源:容器路径 或 源:容器路径:访问模式。访问模式用逗号分隔。

访问模式 作用
rw 读写,省略时就是这个
ro 只读。Gitea 示例里的 /etc/timezone:/etc/timezone:ro 就是这种写法
z SELinux 标记为多个容器共享。没有 SELinux 的系统会忽略
Z SELinux 标记为仅当前容器使用
  • 相对路径从 Compose 文件所在目录计算,并且以 . 或 .. 开头,这样才不会和命名卷重名。短语法的绑定挂载在宿主机路径不存在时会创建目录。要阻止创建,改用长语法,把 bind.create_host_path 设为 false。

  • 长语法里 type 决定 source 怎么写。

type source
volume 顶层 volumes 里的名字
bind 宿主机路径
tmpfs 不写 source
image 镜像引用。子目录用 image.subpath,Compose 2.35.0 起
npipe Windows 命名管道的路径
cluster Swarm 集群卷的名字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
services:
backend:
image: example/backend
volumes:
- type: bind
source: ./config # 宿主机路径
target: /config
read_only: true # 对应短语法的 :ro
bind:
create_host_path: false # 宿主机路径不存在时不要创建,默认 true
propagation: rprivate # 默认。还可写 private、shared、slave、rshared、rslave
selinux: Z # 对应短语法的 Z,另一个值是 z
- type: tmpfs
target: /run
tmpfs:
size: 64m # 字节数或带单位的字符串
mode: 0o755 # 目录权限,Compose 2.14.0 起
- type: image
source: example/assets:1.0
target: /assets
image:
subpath: static # 只挂镜像里的这个子目录
  • consistency 表示挂载一致性要求,取值由运行平台决定。Docker Desktop 上用过 consistent、cached、delegated。

networks

  • networks: 配置网络。

1
2
3
4
5
6
7
8
9
services:
some-service:
networks: # 配置网络
- some-network # 关联网络
- other-network

networks: # 声明网络
some-network:
other-network:
  • 长语法可以给这个服务在某一张网络上单独设置别名和地址。静态地址所在的网段写在顶层 networks 的 ipam 里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
services:
backend:
image: example/backend
networks:
back-tier:
aliases:
- database # 同一网络上的其他容器可以用 database 这个名字访问它
ipv4_address: 172.16.238.10
ipv6_address: 2001:3984:3989::10
networks:
back-tier:
ipam:
config:
- subnet: 172.16.238.0/24
- subnet: 2001:3984:3989::/64
字段 作用
aliases 该网络上的额外主机名。同一个别名可以同时给多个容器,解析到哪一个并不固定
ipv4_address、ipv6_address 加入该网络时使用的静态地址
mac_address 这张网卡的 MAC 地址
link_local_ips 链路本地地址列表
interface_name 容器里这张网卡的接口名,例如 eth0
driver_opts 传给该网络驱动的键值对
priority 连接优先级,默认 0。服务级 mac_address 落在数值最大的那张网卡上
gw_priority 默认网关选数值最大的那张网卡,默认 0

ports

  • ports: 把容器端口映射到宿主机。短语法写成带引号的字符串,避免 YAML 把 80:80 解析成 60 进制数。

1
2
3
4
5
6
7
8
9
services:
web:
image: nginx
ports:
- "8080:80" # 宿主机端口:容器端口,协议默认 tcp
- "127.0.0.1:8081:80" # 只绑定宿主机的这个地址。不写地址时绑定 0.0.0.0
- "9090-9091:8080-8081" # 两边都是范围时,端口个数要相同
- "6060:6060/udp"
- "3000" # 只写容器端口时,宿主机端口由引擎分配
片段 作用
宿主机地址 可省略。省略时绑定 0.0.0.0。IPv6 地址放在方括号里,如 [::1]:6001:6001
宿主机端口 可省略,或写成范围。省略时由引擎分配空闲端口
容器端口 必填,可以是单个端口或范围
协议 tcp 或 udp,默认 tcp
  • 长语法能写短语法里没有的名字和 Swarm 发布方式。

1
2
3
4
5
6
7
8
9
10
11
services:
web:
image: nginx
ports:
- name: web # 给人看的名字
target: 80 # 容器端口
published: "8080" # 宿主机端口,也可以写成 "8083-9000"
host_ip: 127.0.0.1
protocol: tcp
app_protocol: http # Compose 2.26.0 起,给 Compose 的应用协议提示
mode: host # Swarm 使用。host 在每个节点发布端口,ingress 做节点间负载均衡,默认 ingress

network_mode: host 的容器直接使用宿主机网络栈。这种服务再写 ports,运行时会报错。

expose

  • expose: 声明容器向同一 Compose 网络中的其他服务开放的端口。宿主机上不会出现对应的监听端口。

1
2
3
4
5
6
services:
web:
image: nginx
expose:
- "80"
- "8080-8085/tcp" # 协议可以省略,默认 tcp
  • 镜像的 Dockerfile 里已经写了 EXPOSE 时,同一网络中的其他容器也能访问这些端口。

cpus、mem_limit

  • cpu 和 内存限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
services:
backend:
image: myapp:latest
mem_limit: 1g # 限制最多使用1GB内存
mem_reservation: 512m # 建议预留512MB内存
cpus: 2.0 # 限制最多使用2个CPU核
cpu_shares: 1024 # 默认值,表示标准优先级
cpu_quota: 100000 # 每 100ms 容器最多可运行 100ms(=1核), 与 cpus 不能同时设置
cpu_period: 100000 # 调度周期为100ms, 与 cpus 不能同时设置
# cpuset: "0-1" # 只允许跑在这些逻辑 CPU 上,可以写成范围 0-3 或列表 0,1
# cpu_count: 2 # 可用 CPU 个数
# cpu_percent: 50 # 可用 CPU 占本机的百分比
# cpu_rt_runtime: 400ms # 实时调度下,一个周期内允许运行的时间。需要内核支持实时调度
# cpu_rt_period: 1400us # 实时调度周期
# mem_swappiness: 0 # 0 到 100。0 关闭匿名页换出,100 允许全部换出
# memswap_limit: 1g # 内存加交换分区的总上限,要和 mem_limit 一起写
字段名 类型 说明
cpus float 限制容器最多使用多少 CPU(逻辑核数);例如 0.5 = 一半 CPU。0.000 表示不限制
mem_limit string 容器最大内存限制,支持单位:b、k、m、g(如 256m、1g)
mem_reservation string 容器启动时预留的内存,超过这个值不被硬性截断(只提示调度器)
cpu_shares int CPU 权重(默认 1024),多个容器抢 CPU 时才比较这个值
cpu_quota int 每个周期内允许使用的 CPU 时间(单位:微秒)。和 cpus 不要同时写
cpu_period int CPU 调度周期(单位:微秒,默认 100000)。和 cpus 不要同时写
cpuset string 允许运行的逻辑 CPU,如 0-3 或 0,1
cpu_count int 可用 CPU 个数
cpu_percent int 可用 CPU 占本机的百分比
cpu_rt_runtime 时长或微秒 实时调度下,一个周期内允许运行的时间
cpu_rt_period 时长或微秒 实时调度周期
mem_swappiness int 0 到 100,容器匿名页换出到交换分区的倾向
memswap_limit string 内存和交换分区加在一起的上限。mem_limit: 300m 且 memswap_limit: 1g 时,内存最多 300m,交换分区最多 700m。两者相等时容器不能使用交换分区。设为 -1 时交换分区只受宿主机剩余空间限制

查看容器的 cpu 和 内存配置情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 获取容器的 cpu_quota 和 cpu_period
docker inspect --format='{{json .HostConfig.CpuQuota}} {{json .HostConfig.CpuPeriod}}' <container_id>
# 获取容器的 memory_limit
docker inspect --format='{{json .HostConfig.Memory}}' <container_id>
# 获取容器的 cpu_shares
docker inspect --format='{{json .HostConfig.CpuShares}}' <container_id>
# 获取容器的 cpus
docker inspect --format='{{json .HostConfig.NanoCpus}}' <container_id>

# 组合为一个json输出
docker inspect <container_id> | jq '.[0].HostConfig | {
cpus: (.NanoCpus / 1000000000),
cpu_shares: .CpuShares,
mem_limit: (.Memory / 1024 / 1024 | tostring + " MB"),
mem_reservation: (.MemoryReservation / 1024 / 1024 | tostring + " MB"),
cpu_quota: .CpuQuota,
cpu_period: .CpuPeriod
}'

user、working_dir、hostname、init

  • user: 覆盖镜像里的 USER。镜像没写时,进程以 root 运行。

1
2
3
4
5
6
7
services:
web:
image: example/webapp
user: "1000:1000" # 用户,或 用户:组。可以写名字,也可以写数字 id
working_dir: /app # 覆盖镜像里的 WORKDIR
hostname: web # 容器主机名,须是合法的 RFC 1123 主机名
init: true # 在容器里放一个 PID 1,负责转发信号、回收僵尸进程

stdin_open、tty

  • stdin_open 保持标准输入打开,对应 docker run -i。tty 分配一个伪终端,对应 docker run -t。

1
2
3
4
5
services:
web:
image: example/webapp
stdin_open: true
tty: true

stop_signal、stop_grace_period

  • stop_signal 是 Compose 停止容器时发送的信号,默认 SIGTERM。stop_grace_period 是发出该信号后、改发 SIGKILL 之前的等待时间,默认 10s。

1
2
3
4
5
services:
web:
image: example/webapp
stop_signal: SIGTERM
stop_grace_period: 30s

network_mode

  • network_mode: 指定容器的网络模式。写了它就不能再写 networks,Compose 会拒绝这份文件。

值 作用
bridge 接到 Docker 默认网桥。这条网络上不能用服务名互相解析
host 直接使用宿主机网络栈,不要再写 ports
none 关闭容器网络
service:服务名 使用另一个 Compose 服务的网络栈
container:容器名 使用指定容器的网络栈
1
2
3
4
services:
web:
image: nginx
network_mode: host

extra_hosts

  • extra_hosts: 往容器的 /etc/hosts 追加记录。推荐用 主机名=IP。Compose 2.24.1 起也可以写成 主机名:IP。

1
2
3
4
5
6
services:
web:
image: nginx
extra_hosts:
- "db.local=10.0.0.8"
- "myhostv6=[::1]"

dns、dns_search、dns_opt

  • dns、dns_search、dns_opt 分别对应容器 /etc/resolv.conf 里的 DNS 服务器、搜索域和选项。三个字段都可以写成单个字符串或列表。

1
2
3
4
5
6
7
8
9
10
services:
web:
image: nginx
dns:
- 8.8.8.8
- 9.9.9.9
dns_search:
- example.com
dns_opt:
- no-tld-query

mac_address

  • mac_address: 服务级 MAC 地址,Compose 2.24.0 起可以写。Docker Engine 25 及更新版本可能拒绝这个字段,那时改写到 networks.<网络名>.mac_address。

1
2
3
4
services:
web:
image: nginx
mac_address: "02:42:ac:11:00:02"

privileged

  • privileged: true 时容器以特权运行,能力接近宿主机。只在设备或内核功能确实需要时打开。

1
2
3
4
services:
web:
image: example/webapp
privileged: true

cap_add、cap_drop

  • cap_add 追加 Linux 能力,cap_drop 去掉能力。ALL 表示全部。

1
2
3
4
5
6
7
services:
web:
image: example/webapp
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # 允许绑定 1024 以下的端口

security_opt

  • security_opt: 覆盖容器默认的安全标签。布尔项可以只写名字,效果等同于 =true。

1
2
3
4
5
6
services:
web:
image: example/webapp
security_opt:
- no-new-privileges:true # 进程不能再提升权限
- label=user:USER

devices

  • devices: 把宿主机设备映射进容器,格式是 宿主机路径:容器路径[:权限]。权限是 r 读、w 写、m 创建设备节点。也可以写 CDI 设备名。

1
2
3
4
5
6
7
services:
web:
image: example/webapp
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
- "/dev/sda:/dev/xvda:rwm"
# - "vendor1.com/device=gpu"

group_add

  • group_add: 让容器里的用户额外加入这些组。可以写组名或组号。多个容器要读写同一个卷上的文件时,把它们加进同一个组。

1
2
3
4
5
6
services:
web:
image: alpine
group_add:
- mail
- "100"

gpus

  • gpus: 分配 GPU。写成 all 表示使用全部。列表里用 driver 和 count 按数量分配,或用 device_ids 指定设备。

1
2
3
4
5
6
7
8
9
10
services:
model:
image: example/model
gpus: all
# gpus:
# - driver: nvidia
# count: 1
# - driver: nvidia
# device_ids:
# - "0"

read_only、tmpfs

  • read_only: true 时容器根文件系统只读。需要写入的目录另外挂 tmpfs 或卷。

1
2
3
4
5
6
7
services:
web:
image: example/webapp
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid,size=16m # 冒号后是逗号分隔的挂载选项
- /run:mode=755,uid=1000,gid=1000 # mode 是权限,uid、gid 是属主
选项 作用
rw 这块内存文件系统可读写
noexec 不能在这个目录里执行程序
nosuid 忽略这里文件上的 setuid、setgid
size 容量上限,写成 size=16m。m 表示 MiB,还可以用 k、g
mode 目录权限,如 mode=755
uid、gid 属主的用户号和组号
  • 这是服务级 tmpfs,挂一块临时内存文件系统。短语法的容量写在选项里,例如 size=16m。写在 volumes 里且 type: tmpfs 时,容量和权限分别写 tmpfs.size、tmpfs.mode。

pull_policy、platform

  • pull_policy: 启动时如何处理镜像。

值 作用
missing 本机没有这张镜像才拉取。未使用 Build Specification 时的默认值。if_not_present 是它的旧名。标签为 latest 时仍然每次都拉
always 每次都从仓库拉取
never 只使用本机镜像。本机没有就失败
build 构建镜像。本机已经有也重新构建
daily 距离上次拉取超过 24 小时才检查仓库
weekly 距离上次拉取超过 7 天才检查仓库
every_<时长> 距离上次拉取超过这个时长才检查。单位可以是 w、d、h、m、s,例如 every_12h
1
2
3
4
5
services:
web:
image: nginx
pull_policy: every_12h
platform: linux/amd64 # 拉取或构建所针对的平台,格式 os[/arch[/variant]]

profiles

  • profiles: 给服务挂上配置档名称。没有 profiles 的服务每次都会启动;写了的服务,只有命令行带上同名 --profile 才会启动。名称须匹配 [a-zA-Z0-9][a-zA-Z0-9_.-]+。

1
2
3
4
5
services:
phpmyadmin:
image: phpmyadmin
profiles:
- debug
1
2
# 不带 --profile 时,phpmyadmin 不会启动
docker compose --profile debug up -d

scale

  • scale: 这个服务默认启动的容器个数。命令行 docker compose up --scale 服务名=数量 只影响这一次。写了 container_name 时个数只能是 1。

1
2
3
4
services:
web:
image: nginx
scale: 3

extends

  • extends: 复用另一个服务的配置。service 是被引用的服务名,file 可省略,省略时表示当前这个 Compose 文件。

1
2
3
4
5
6
7
services:
web:
extends:
file: common.yml # 相对路径相对于当前 Compose 文件
service: webapp
environment:
PORT: "8080" # 映射类字段按键覆盖;被引用服务里其余的键仍保留
合并方式 适用情况
按键覆盖 environment、labels、sysctls、healthcheck 这类映射。当前文件里出现的键覆盖被引用服务的同名键
列表拼接 ports、expose、cap_add、secrets 等。被引用的项在前,当前文件的项在后,重复项去掉
标量取当前文件 image、user 这类单值。当前文件写了就用当前文件的
  • 被引用服务依赖的 volumes、networks、configs、secrets、depends_on 不会自动带过来,当前文件里要再声明一次。extends 不能循环引用。docker stack deploy 不支持 extends。

shm_size

  • shm_size: /dev/shm 的大小,写成字节数或带单位的字符串。

1
2
3
4
services:
web:
image: example/webapp
shm_size: 1gb

ulimits

  • ulimits: 覆盖容器的资源限制。只写一个整数时软限制和硬限制相同;分开写时用 soft 和 hard。

1
2
3
4
5
6
7
8
services:
web:
image: example/webapp
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000

pids_limit

  • pids_limit: 容器内允许的进程数。-1 表示不限制。

1
2
3
4
services:
web:
image: example/webapp
pids_limit: 100

sysctls

  • sysctls: 设置容器命名空间内的内核参数。会改到宿主机的参数不能写在这里。可以用映射或列表。

1
2
3
4
5
6
services:
web:
image: nginx
sysctls:
net.core.somaxconn: 1024
net.ipv4.tcp_syncookies: 0

pid

  • pid: 进程号空间。Docker Engine 上常用 host(和宿主机共用)或 service:服务名(加入那个服务的进程号空间)。

1
2
3
4
5
services:
web:
image: nginx
pid: "host"
# pid: "service:db"

labels

  • labels: 给容器加元数据。建议用反向 DNS 作为键,避免和其他软件冲突。映射和列表都可以。

1
2
3
4
5
6
services:
web:
image: nginx
labels:
com.example.description: "web"
com.example.department: "ops"

logging

  • logging: 这个服务的日志驱动。driver 的可选值由运行时决定,本机常见 json-file(默认)、local、syslog、none。options 是驱动自己的参数。

1
2
3
4
5
6
7
8
services:
web:
image: nginx
logging:
driver: json-file
options:
max-size: "10m" # 单个日志文件上限
max-file: "3" # 保留的文件个数

secrets

  • secrets: 把顶层 secrets 里的敏感数据以只读文件挂进容器。短语法挂到 /run/secrets/<名字>。顶层声明了密钥,服务里没有写 secrets,容器也读不到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
services:
web:
image: example/webapp
secrets:
- server-certificate # 文件名就是 server-certificate
- source: my-token
target: token # 容器里的文件名,默认等于 source
uid: "103"
gid: "103"
mode: 0o440 # 默认 0444。写权限会被忽略
secrets:
server-certificate:
file: ./server.cert
my-token:
environment: MY_TOKEN # 从执行 Compose 时的环境变量读取
  • uid、gid、mode 只在密钥来源是 environment 时生效。来源是 file 时 Compose 用绑定挂载,这三个字段会被忽略。

configs

  • configs: 把顶层 configs 里的文件挂进容器,用来放证书、配置,而不是密钥。短语法在 Linux 容器里挂到 /<配置名>,默认权限 0444。

1
2
3
4
5
6
7
8
9
10
11
12
services:
web:
image: nginx
configs:
- source: nginx_conf
target: /etc/nginx/nginx.conf
uid: "103"
gid: "103"
mode: 0o440
configs:
nginx_conf:
file: ./nginx.conf

pre_start

  • pre_start: 服务容器启动前,按顺序跑一组临时容器。每一步退出码为 0 才继续;depends_on 满足之后才开始。临时容器加入同一网络,并挂上该服务声明的卷。同一定义已经成功过的步骤,下次 up 或容器按 restart 重启时不会再跑;定义变了、上次失败、或服务被重建时会再跑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
services:
app:
image: example/webapp
depends_on:
db:
condition: service_healthy
volumes:
- data:/data
pre_start:
- command: ["./manage.py", "migrate"] # 不写 image 时用本服务的镜像
- image: busybox
command: sh -c 'chown -R 1000:1000 /data'
user: root
db:
image: postgres:16
volumes:
data:
  • per_replica: false 时,这一步在所有副本启动前只跑一次。它只能看见命名卷和绑定挂载,看不见每个副本自己的 tmpfs 或匿名卷。

post_start

  • post_start: 容器已经启动之后,在这个容器里面执行。具体在启动后的哪一刻,Compose 没有进一步保证。

pre_stop

  • pre_stop: 停止容器之前,在这个容器里面执行,字段和 post_start 相同。容器自己退出,或被直接杀掉时,这些命令不会跑。

1
2
3
4
5
6
7
8
9
10
11
12
services:
web:
image: example/webapp
post_start:
- command: ./on_start.sh
user: root
privileged: true
working_dir: /app
environment:
- FOO=BAR # 在服务环境变量之上追加或覆盖,只对这条命令有效
pre_stop:
- command: ./on_stop.sh

develop

  • develop: 配合 docker compose watch。watch 里每一项都要有 path 和 action。sync、sync+restart 还要写 target,表示容器内的同步目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
services:
web:
image: example/webapp
build: .
develop:
watch:
- action: sync # 把文件同步进正在运行的容器
path: ./web
target: /app/web
ignore:
- node_modules/
- action: rebuild # 重新构建镜像并重建容器
path: package.json
- action: sync+restart # 同步之后重启容器
path: ./assets
target: /app/assets
action 作用
sync 把 path 同步到容器内的 target
rebuild 重新构建镜像并重建容器
restart 重启容器
sync+restart 先同步到 target,再重启容器

docker run 转 docker compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装命令,npm安装:https://nodejs.org/zh-cn/download
npm install composerize -g
# 运行命令
composerize docker run -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --restart always --log-opt max-size=1g nginx
## 转换结果
name: <your project name>
services:
nginx:
ports:
- 80:80
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
restart: always
logging:
options:
max-size: 1g
image: nginx

docker compose 编排管理工具 Dockge

  • Dockge 是一个开源轻量级「Docker Compose 管理器」,它提供了一个漂亮、响应迅速的 Web 界面,专门面向使用 docker compose 的用户。

功能模块 主要描述
Compose 堆栈全生命周期管理 可以创建、编辑、启动、停止、重启、删除基于 compose.yaml 文件的 Docker 堆栈
交互式 Compose 编辑器 + Web 终端 实时编辑 YAML 并查看输出,还可以直接在浏览器中操作终端
将 docker run … 命令转换为 Compose 文件 快速生成 compose.yaml,便于版本控制和结构管理
实时操作反馈 镜像拉取、堆栈启动/停止等操作均可实时查看进度
多主机代理支持(≥1.4.0) 能在单一 UI 中管理多个 Docker 主机
高兼容性 & 安全设计 Compose 文件保存在本地,不会被系统托管,便于使用 CLI 或其他工具管理
  • 安装

1
2
3
4
5
6
7
8
9
10
11
# Create directories that store your stacks and store Dockge's stack
mkdir -p /opt/stacks /opt/dockge
cd /opt/dockge

# Download your compose.yaml
curl "https://dockge.kuma.pet/compose.yaml?port=5001&stacksPath=%2Fopt%2Fstacks" --output compose.yaml

# Start the Server
docker compose up -d

# 浏览器访问 http://localhost:5001,初次登录时需要注册账号密码,该账号即为 Dockge 的管理员账号