Docker Compose 多容器编排实战
- 1Docker 入门与实战
- 2Docker Compose 多容器编排实战本文
- 3Kubernetes 核心概念与实战入门
- 4CI/CD 持续集成与部署实战
1. 为什么需要 Compose
一个正经项目很少只有一个容器:前端要 Nginx 托管静态资源,后端跑 Node 或 Spring,数据存 PostgreSQL,缓存用 Redis。全靠 docker run 手动拉起,大概是这样:
docker network create shop-netdocker run -d --name shop-db --network shop-net \ -e POSTGRES_PASSWORD=secret -v shop-db-data:/var/lib/postgresql/data \ postgres:16-alpinedocker run -d --name shop-api --network shop-net \ -e DATABASE_URL=postgres://app:secret@shop-db:5432/shop \ -p 3000:3000 sakura/shop-api:1.0.0这套写法的痛点:
- 顺序靠人肉保证。数据库没起来,后端就连不上然后退出,得盯着日志等重试。
- 参数散落在终端历史里。换机器、换同事就得重新拼,没法版本管理。
- 状态不可复现。网络名、卷名随手起,删掉重来全散了。
- 没有单一可信来源。改一个端口要在多处同步。
Compose 把这一堆命令抽象成声明式 YAML:你只描述想要什么(有哪些服务、用什么镜像、依赖谁、挂什么卷),创建网络、按序启动、注入变量这些”怎么做”交给 docker compose up。好处是这份 YAML 能进 Git、能 review、能被 CI 复用——新人 clone 后一条命令就得到与你一致的环境。
Compose 与 Kubernetes 的定位区别
二者不是替代关系,是不同层次的工具。
| 维度 | Docker Compose | Kubernetes |
|---|---|---|
| 定位 | 单机多容器编排 | 集群级容器编排 |
| 学习曲线 | 低,一个 YAML 文件 | 高,概念众多 |
| 部署目标 | 本地开发、CI、单机小型生产 | 多节点大规模生产 |
| 高可用 | 单机,无跨节点自愈 | 副本调度、自愈、滚动更新 |
| 伸缩 | --scale 有限,受单机约束 | HPA 自动伸缩 |
| 网络 | 单主机 bridge | CNI 插件,跨节点组网 |
| 存储 | 命名卷 / 绑定挂载 | PV / PVC / StorageClass |
| 典型场景 | 本地开发、边缘、中小项目 | 云原生生产、微服务集群 |
结论:开发环境无脑用 Compose,生产看规模。单机够用、没有多节点诉求的项目,Compose 上生产完全可行;等需要多副本、滚动发布、跨节点容灾时再迁 K8s,服务划分思路还能直接复用。
2. 核心概念
- 项目(project):一组关联服务的集合,是 Compose 的操作单元。默认取当前目录名,可用顶层
name或-p指定。项目名决定容器、网络、卷的命名前缀。 - 服务(service):一个抽象应用组件,描述用什么镜像、怎么配置、依赖谁。服务不是容器,而是容器的模板。
- 容器(container):服务实例化后的运行体。一个服务默认跑一个容器,
--scale可拉起多个。 - 网络(network):服务间通信的虚拟网络,同网服务可用服务名互访。
- 卷(volume):持久化数据的载体,容器删了数据还在,数据库靠它。
compose.yaml 与 docker-compose.yml 的历史
早期 Compose 是独立 Python 工具,命令为 docker-compose(连字符),默认文件名 docker-compose.yml。Compose V2 用 Go 重写,以插件形式集成进 Docker CLI,命令变成 docker compose(空格)。
- 新项目用
compose.yaml,这是官方当前首选。 docker-compose.yml仍被支持,属向后兼容,旧项目不必急着改名。- Compose 按
compose.yaml、compose.yml、docker-compose.yaml、docker-compose.yml顺序查找,命中即用;同目录只保留一个。 - 命令统一用 V2 的
docker compose,旧的docker-compose二进制已进入维护模式。
3. compose.yaml 完整结构
name: my-project
services: web: image: nginx:1.27-alpine
networks: frontend:
volumes: db-data:
configs: nginx-conf: file: ./nginx/nginx.conf
secrets: db-password: file: ./secrets/db-password.txt关于 version 字段
老配置顶部常写着 version: "3.8"。这个字段已经废弃(obsolete),Compose V2 会忽略它,执行 docker compose config 时甚至打印一条警告。它的历史作用是区分文件格式版本,而 V2 CLI 已统一格式,所以新项目不要写。
| 字段 | 作用 | 常用度 |
|---|---|---|
name | 指定项目名,影响资源命名前缀 | 常用 |
services | 定义所有服务,唯一必填字段 | 必填 |
networks | 自定义网络,做隔离与分组 | 常用 |
volumes | 命名卷,做数据持久化 | 常用 |
configs | 注入非敏感配置文件 | 按需 |
secrets | 注入敏感信息,不进环境变量 | 按需 |
include | 引入其他 compose 文件做模块化 | 进阶 |
x-* | 自定义扩展字段,配合 YAML 锚点 | 进阶 |
省略 networks 时,Compose 自动创建 项目名_default 网络,把所有服务接进去。
4. 服务定义详解
image 与 build
services: api: build: context: ./backend # 构建上下文 dockerfile: Dockerfile # 默认即为 Dockerfile args: # 构建期变量,对应 Dockerfile 的 ARG NODE_ENV: production target: runtime # 多阶段构建指定阶段 image: sakura/shop-api:1.0.0context 是构建上下文,Dockerfile 的 COPY 只能引用其内部文件;args 是构建期变量,不进容器运行时;target 指定多阶段构建停在哪个阶段(生产用 runtime、开发用 development)。image 与 build 同现时,image 给构建产物打标签,方便 docker compose push。
container_name
指定容器名便于 docker exec -it shop-web sh,但代价是不能 --scale(会命名冲突),多副本场景不要设它。
ports 与 expose
services: web: image: nginx:1.27-alpine ports: - "8080:80" # 宿主机 8080 → 容器 80 - "127.0.0.1:9000:9000" # 只绑本机回环 api: image: sakura/shop-api:1.0.0 expose: - "3000" # 仅内部网络可见,不映射宿主机ports 映射到宿主机;expose 只声明端口供同网服务访问。只该被内部调用的后端用 expose 更安全。
environment 与 env_file
services: api: environment: NODE_ENV: production DATABASE_URL: postgres://app:${POSTGRES_PASSWORD:-secret}@db:5432/shop env_file: - .envenvironment 直接写键值对并支持插值;env_file 从文件批量读取。列表形式 - KEY=VALUE 与映射形式 KEY: VALUE 等价。
command 与 entrypoint
command 覆盖镜像 CMD(默认参数),entrypoint 覆盖 ENTRYPOINT(可执行入口),最终命令由二者拼接。例如:
services: cache: image: redis:7-alpine command: ["redis-server", "--appendonly", "yes"]推荐列表(exec form)而非字符串,避免 shell 解析带来的信号处理问题。
restart 策略对比
| 策略 | 行为 | 适用 |
|---|---|---|
no | 不自动重启(默认) | 一次性任务、调试 |
always | 无论退出码都重启 | 长驻服务,但手动 stop 也会被拉起 |
on-failure | 仅非 0 退出时重启 | 偶发失败的任务 |
on-failure:3 | 非 0 退出最多重启 3 次 | 限制重启,避免死循环 |
unless-stopped | 始终重启,除非被手动 stop | 生产最常用 |
5. 依赖与启动顺序
depends_on 的两种语法
短语法只表达启动顺序:
services: api: depends_on: - db - cache长语法可带条件:
services: api: depends_on: db: condition: service_healthy restart: true cache: condition: service_started| condition | 含义 |
|---|---|
service_started | 容器已启动(默认行为,不等就绪) |
service_healthy | 通过健康检查,真正就绪 |
service_completed_successfully | 容器成功退出(退出码 0),适合迁移任务 |
为什么 depends_on 不等于就绪等待
这是最常见的坑。默认 depends_on 只保证启动顺序:先 docker run db,再轮到 api。但”已启动”和”服务可用”是两回事——PostgreSQL 启动后还要初始化数据目录、启动进程、监听 5432,可能耗时数秒。这期间 api 去连库会直接 connection refused 退出,于是出现经典现象:第一次 up 挂,再 up 一次就好。正解是 depends_on + healthcheck 组合:
services: db: image: postgres:16-alpine environment: POSTGRES_USER: app POSTGRES_PASSWORD: secret POSTGRES_DB: shop healthcheck: test: ["CMD-SHELL", "pg_isready -U app -d shop"] interval: 10s timeout: 5s retries: 5 start_period: 30s
api: image: sakura/shop-api:1.0.0 depends_on: db: condition: service_healthyapi 会等到 db 健康检查通过才启动,从根上消除竞态。
healthcheck 参数与写法
| 参数 | 含义 | 默认值 |
|---|---|---|
test | 检查命令 | 无(不写即无检查) |
interval | 检查间隔 | 30s |
timeout | 单次超时 | 30s |
retries | 连续失败多少次判 unhealthy | 3 |
start_period | 启动宽限期,期间失败不计入 retries | 0s |
test 有两种写法:["CMD", "curl", "-f", "..."] 直接执行命令,不经 shell;["CMD-SHELL", "pg_isready -U app && ..."] 交给 shell,支持管道与 &&。start_period 很关键,慢启动的 Java 应用通常给 30s 到 60s,避免没起来就被判 unhealthy 反复重启。
6. 网络
不定义 networks 时,Compose 自动建一个 项目名_default bridge 网络,全部服务接入,服务间用服务名互访:
services: api: environment: DATABASE_URL: postgres://app:secret@db:5432/shop REDIS_URL: redis://cache:6379这就是 Compose 最省心之处——服务名即 DNS 名,内置 DNS 把服务名解析到对应容器 IP,重启换 IP 也不影响。
默认网络是扁平的,所有服务互相可见。生产里通常分层隔离:
services: web: networks: [frontend] api: networks: [frontend, backend] db: networks: [backend] cache: networks: [backend]
networks: frontend: backend:这样 web 只能访问 api,碰不到 db 和 cache;db 与 cache 完全不可从外部网络访问;api 是唯一桥接点,这是最小权限原则在网络层的落地。容器访问宿主机则通过 extra_hosts 加上 host.docker.internal:host-gateway。
7. 数据持久化
容器删除后可写层数据即丢,要 survive 重建必须落到容器之外:
services: db: image: postgres:16-alpine volumes: - db-data:/var/lib/postgresql/data # named volume,Docker 管理 - ./init:/docker-entrypoint-initdb.d:ro # bind mount,宿主机路径,只读 - /var/lib/postgresql/wal # 匿名卷,自动命名
volumes: db-data:| 类型 | 写法 | 数据位置 | 适用 |
|---|---|---|---|
| named volume | db-data:/path | Docker 管理目录 | 数据库、需 Docker 管理的数据 |
| bind mount | ./data:/path | 宿主机指定路径 | 代码热重载、配置、日志 |
| 匿名卷 | /path | Docker 自动命名 | 临时屏蔽镜像内目录 |
生产里数据库一律用 named volume:性能更好,跨平台一致,备份有标准工具。bind mount 更适合挂源码和宿主机已有目录。数据库持久化写法如下,其中 ${POSTGRES_PASSWORD:?...} 表示变量必须提供,否则直接报错退出,防止默认密码上线:
services: db: image: postgres:16-alpine environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} volumes: - db-data:/var/lib/postgresql/data
volumes: db-data:卷的备份与迁移
# 备份:把 db-data 内容打包到当前目录docker run --rm -v shop_db-data:/data -v "$PWD":/backup \ alpine tar czf /backup/db-data-backup.tar.gz -C /data .
# 恢复:解包到一个新卷docker volume create shop_db-data-restoredocker run --rm -v shop_db-data-restore:/data -v "$PWD":/backup \ alpine tar xzf /backup/db-data-backup.tar.gz -C /data生产更推荐数据库自带的逻辑备份(pg_dump、mysqldump),格式更稳、可跨版本迁移;卷级物理备份只适合整机迁移或快速回滚。
8. 环境变量与配置管理
Compose 默认读取项目根目录的 .env 做变量插值。它和服务的 env_file 是两回事:.env 给 Compose 自己用、参与 ${VAR} 插值;env_file 把变量注入到某个服务的容器里。
POSTGRES_PASSWORD=change-me-in-productionAPP_PORT=8080| 语法 | 含义 |
|---|---|
${VAR} | 直接取值,未定义则替换为空 |
${VAR:-default} | 未定义或为空时用默认值 |
${VAR-default} | 未定义时用默认值(空串也算已定义) |
${VAR:?err} | 未定义或为空时报错退出,适合必填项 |
${VAR:+alt} | 已定义时用 alt |
$$VAR | 转义,输出字面量 $VAR |
多环境与 -f 叠加
不同环境的差异不必复制整份文件,Compose 默认会自动读取 compose.override.yaml 叠加到 compose.yaml 上:
# compose.override.yaml —— 开发专用覆盖services: api: build: target: development command: npm run dev environment: NODE_ENV: development也可显式叠加任意文件:docker compose -f compose.yaml -f compose.prod.yaml up -d。规则是后者覆盖前者的同名标量字段,列表字段合并,所以生产覆盖文件只写差异项。验证合并结果用 docker compose -f ... config。
不要把密钥写进仓库
.env只放非敏感默认值,真实密钥由 CI 变量或部署环境注入。.gitignore加上.env、*.local、secrets/,并提供.env.example入库作模板。- 极敏感凭据用顶层
secrets以文件挂载方式注入,而非环境变量——环境变量会出现在docker inspect和子进程环境里,容易泄漏。
9. 完整实战:前后端全栈一键启动
一个可直接运行的全栈项目:React 前端(构建为静态资源交给 Nginx)+ Node 后端 + PostgreSQL + Redis。
shop/├── compose.yaml├── .env├── frontend/ # React + Dockerfile├── backend/ # Node + Dockerfile└── init/ └── 01-schema.sqlname: shop
services: web: build: context: ./frontend args: NODE_ENV: production image: sakura/shop-web:1.0.0 ports: - "${APP_PORT:-8080}:80" depends_on: api: condition: service_healthy networks: [frontend] restart: unless-stopped
api: build: context: ./backend target: runtime image: sakura/shop-api:1.0.0 environment: NODE_ENV: production DATABASE_URL: postgres://app:${POSTGRES_PASSWORD:?required}@db:5432/shop REDIS_URL: redis://cache:6379 expose: - "3000" depends_on: db: condition: service_healthy cache: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 10s timeout: 3s retries: 5 start_period: 20s networks: [frontend, backend] restart: unless-stopped
db: image: postgres:16-alpine environment: POSTGRES_USER: app POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?required} POSTGRES_DB: shop volumes: - db-data:/var/lib/postgresql/data - ./init:/docker-entrypoint-initdb.d:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U app -d shop"] interval: 10s timeout: 5s retries: 5 start_period: 20s networks: [backend] restart: unless-stopped
cache: image: redis:7-alpine command: ["redis-server", "--appendonly", "yes"] volumes: - cache-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 networks: [backend] restart: unless-stopped
networks: frontend: backend:
volumes: db-data: cache-data:配套的 .env 只需 POSTGRES_PASSWORD=change-me-in-production 与 APP_PORT=8080。逐个服务解释:
- web:从
frontend/Dockerfile多阶段构建,产物由容器内 Nginx 托管,映射到宿主机APP_PORT。只接入frontend网络,碰不到数据库;依赖 api 健康检查通过才启动,避免一打开就 502。 - api:
target: runtime使用生产阶段。DATABASE_URL、REDIS_URL直接写服务名db、cache,靠内置 DNS 解析。用expose而非ports,因为不该被公网直连;健康检查命中/health。 - db:数据落在 named volume
db-data,容器重建不丢;init/挂进初始化目录,首次启动自动执行01-schema.sql建表;pg_isready保证真正就绪。 - cache:Redis 开 AOF 持久化,数据落
cache-data卷,redis-cli ping返回 PONG 即健康。 - networks:
frontend面向外部,backend是数据层,通过 api 桥接,最小暴露。 - volumes:两个命名卷承载有状态数据,独立于容器生命周期。
启动与验证:
docker compose up -d --build # 构建并后台启动docker compose ps # 确认均为 healthycurl -I http://localhost:8080 # 验证前端docker compose exec api curl -f http://localhost:3000/health10. 常用命令
| 命令 | 作用 |
|---|---|
docker compose up -d | 后台启动全部服务 |
docker compose up -d --build | 强制重建镜像后启动 |
docker compose down | 停止并删除容器、网络 |
docker compose down -v | 同时删除命名卷(数据一并清空) |
docker compose ps | 列出服务状态 |
docker compose logs -f api | 实时跟踪某服务日志 |
docker compose logs --tail=100 web | 只看最近 100 行 |
docker compose exec api sh | 在运行中的容器开会话 |
docker compose run --rm api npm test | 一次性容器跑命令,跑完即删 |
docker compose build --no-cache | 不用缓存重建 |
docker compose pull | 拉取最新镜像 |
docker compose restart api | 重启指定服务 |
docker compose config | 输出合并后的最终配置 |
docker compose top | 查看服务内进程 |
docker compose stats | 实时资源占用 |
几个必须提醒的点:
down -v会删数据卷,本地清环境很方便,生产上等于毁库,执行前务必确认。up -d --build与up -d的区别是是否重建镜像。改了 Dockerfile 或构建上下文代码却没带--build,跑的还是旧镜像。logs -f配--tail更好用:--tail=200 -f既看历史又跟新日志。run与exec的区别:run启动新容器执行(默认不映射端口),exec在已运行的容器里执行;一次性任务用run --rm。
11. 开发与生产的差异
开发要改代码立刻生效,用绑定挂载 + 开发模式:
services: api: build: target: development command: npm run dev volumes: - ./backend:/app - /app/node_modules # 匿名卷遮蔽,防止宿主机空目录覆盖容器内依赖 ports: - "3000:3000" environment: NODE_ENV: development- /app/node_modules 这一行别漏:它用匿名卷遮蔽容器内目录,防止宿主机空目录或不同平台安装的二进制覆盖容器依赖,否则经常报模块找不到。
生产则用构建好的不可变镜像,把源码挂进去是反模式;资源限制、日志轮转等差异项写进 compose.prod.yaml,用 -f 叠加。
调试工具、一次性任务不该在正常启动时被拉起,用 profiles 打标签,默认 up 时不会启动:
services: adminer: image: adminer:4 profiles: ["debug"] ports: - "8081:8080"激活用 docker compose --profile debug up -d 或 docker compose --profile tools run --rm migrate。一份文件同时服务开发、调试、运维多种场景,比维护多份文件清爽。
12. 生产注意事项
资源限制:Compose V2 中 deploy.resources 下的 limits 会直接生效(不需要 swarm 模式)。
services: api: deploy: resources: limits: cpus: "1.0" memory: 512M reservations: memory: 256M老写法 mem_limit、cpus 仍可用,但 deploy.resources 是推荐格式,也便于日后迁移 K8s。单机下 reservations 意义有限,主要靠 limits 防内存泄漏拖垮整机。
日志驱动与大小限制:默认 json-file 驱动不会自动清理,日志会一直涨到撑爆磁盘,生产必须加限制。
services: api: logging: driver: json-file options: max-size: "10m" max-file: "3"含义是单文件最大 10MB、最多保留 3 个,滚动覆盖。也可用默认就压缩轮转的 local 驱动,或把日志发往 ELK、Loki 等集中式系统。
重启策略与镜像版本固定:生产统一 restart: unless-stopped;绝不使用 latest 标签——postgres:latest 某天 pull 下来一个不兼容新版本就可能炸库,固定到 postgres:16.3-alpine 这样具体版本;自建镜像用语义化 tag(sakura/shop-api:1.0.0)。
健康检查必配:每个长驻服务都该有 healthcheck,它是 depends_on 的条件来源,也是外部监控判断存活的依据。没有健康检查的服务崩溃可能悄无声息地持续几小时。
13. 从 Compose 到 Kubernetes
什么时候该升级
- 单机资源撑不住,需要多节点横向扩展。
- 需要多副本 + 负载均衡,而不只是单实例。
- 需要滚动更新、灰度发布、自动回滚。
- 需要自动扩缩容(按 CPU/内存/QPS 增减副本)。
- 需要跨节点容灾,单机挂了业务还能跑。
- 团队规模上来,需要命名空间隔离与 RBAC。
如果只是想要一个能跑、够用的部署,Compose 完全没必要换,别为时髦给自己加运维负担。
| Docker Compose | Kubernetes | 说明 |
|---|---|---|
| service | Deployment | 服务定义 → 副本控制器 |
| service 单实例 | Pod | 最小调度单元 |
| ports | Service / Ingress | 端口暴露与路由 |
| networks | Service / NetworkPolicy | 服务发现与网络隔离 |
| named volume | PersistentVolumeClaim | 持久化存储声明 |
| bind mount | hostPath / ConfigMap | 宿主挂载或配置注入 |
| environment / env_file | ConfigMap / Secret | 配置与密钥 |
| healthcheck | livenessProbe / readinessProbe | 存活与就绪探针 |
| depends_on | initContainers | 启动依赖 |
| profiles | namespace / Helm values | 环境与场景隔离 |
| restart | restartPolicy(Pod 级) | 重启策略 |
| deploy.resources | resources.requests/limits | 资源配额 |
--scale | replicas / HPA | 副本数 |
映射相当直观:服务怎么切分、网络怎么隔离、哪些有状态,这些设计在 Compose 阶段想清楚,迁移时基本照搬。所以用 Compose 认真组织项目,本身就是给未来上 K8s 铺路。
14. 常见问题排查
容器起来了但连不上数据库:症状是后端启动后立即退出,日志里 ECONNREFUSED 或 could not connect to server。
- 只写了
depends_on: [db]却没配condition: service_healthy,api 在 db 就绪前就去连,加上健康检查条件即可。 - 连接地址写错。容器里不能用
localhost连数据库——那是 api 容器自己,必须用服务名db:5432。 - 两个服务不在同一网络,检查各自
networks是否有交集。
端口冲突:报错 bind: address already in use,说明宿主机端口被占用,用 docker ps --format '{{.Names}} {{.Ports}}' | grep 8080 定位。解决方式是换宿主机端口("8081:80")或停掉占用进程。冲突只看宿主机侧端口,容器内端口可以重复。
卷权限问题:PostgreSQL 等应用报 Permission denied,通常是宿主路径(bind mount)属主与容器内用户不匹配。named volume 一般没这问题,是首选;bind mount 场景可用 user: 对齐 UID/GID,或调整宿主机目录权限。
容器内 DNS 解析失败:报 bad address 或 Name or service not known。检查服务是否真的在同一自定义网络;检查服务名拼写与 services: 下的键是否完全一致(区分大小写);手动加了自定义网络却漏掉对方服务也会解析不到。
配置不生效:改了 compose 文件但行为没变,先用 docker compose config 输出插值、合并后的最终配置,看到的内容与预期不符,问题就在这里。另外改了代码却没加 --build,跑的还是旧镜像,也会造成”配置没生效”的错觉。
15. 命令与配置速查表
常用命令
| 命令 | 作用 |
|---|---|
docker compose up -d | 后台启动全部服务 |
docker compose up -d --build | 重建镜像后启动 |
docker compose down | 停止并删除容器与网络 |
docker compose down -v | 同时删除命名卷(清数据) |
docker compose ps | 查看服务状态 |
docker compose logs -f api | 实时跟踪日志 |
docker compose exec api sh | 进入运行中的容器 |
docker compose run --rm api cmd | 一次性容器执行命令 |
docker compose config | 验证并输出最终配置 |
docker compose restart api | 重启服务 |
服务常用字段
| 字段 | 作用 |
|---|---|
image / build | 镜像来源 |
container_name | 指定容器名(不可与 scale 共用) |
ports / expose | 对外映射 / 仅内部暴露 |
environment / env_file | 环境变量注入 |
command / entrypoint | 覆盖启动命令 |
depends_on | 启动依赖与条件 |
healthcheck | 健康检查 |
volumes / networks | 数据持久化 / 网络接入 |
restart | 重启策略 |
deploy.resources | 资源限制 |
logging | 日志驱动与轮转 |
profiles | 按需启动分组 |
插值语法与可选值
| 语法 / 项 | 含义或可选值 |
|---|---|
${VAR} | 直接取值,未定义则为空 |
${VAR:-default} | 未定义或空时用默认值 |
${VAR:?err} | 未定义时直接报错 |
${VAR:+alt} | 已定义时替换为 alt |
$$VAR | 转义为字面量 |
depends_on.condition | service_started / service_healthy / service_completed_successfully |
restart | no / always / on-failure[:N] / unless-stopped |
healthcheck.test | ["CMD", ...] / ["CMD-SHELL", "..."] |
| 日志驱动 | json-file / local / syslog / fluentd / gelf |
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!













