---
description: Docker Compose 部署（拉镜像 / 重建容器；后端反代 + HTTPS 由部署引擎统一接管，配了域名即自动配反代）
applicable: [docker]
requires: [docker]
buildSource: none
variables:
  - key: deployRoot
    label: compose 文件所在目录
    default: "/opt/{{project}}"
    required: true
  - key: service
    label: 服务名（留空 = 全部）
    required: false
  - key: composeCmd
    label: compose 命令（留空 = 自动探测 docker compose / docker-compose）
    required: false
  - key: upstreamPort
    label: 反代端口
    default: "8080"
    required: false
  - key: sslEmail
    label: SSL 邮箱
    required: false
---

# Docker Compose

buildSource=none：不上传产物，直接在服务器上 `compose pull && up -d`（适合镜像已推到 registry / 已 docker load 的场景）。
若你要先在服务器上 build 镜像，把 target 的 buildSource 改成 `server`，并在下方加 `stage:build` 代码块。

> 前提：`{{deployRoot}}/docker-compose.yml` 已在服务器上（或在 build 阶段生成）。
> **compose 命令自动探测**：优先 `docker compose`（v2 插件），不可用则回退 `docker-compose`（v1）；
> 也可在 composeCmd 变量里手动指定。每个代码块独立执行，故探测一行需在每块重复。
>
> **反向代理 + HTTPS 由部署引擎接管**：部署目标配了域名时，引擎自动用「网站」系统 render_reverse_proxy
> 建 `reeve-<域名>.conf`（域名 → 127.0.0.1:反代端口）；勾 HTTPS + 填邮箱即 certbot 自动签。本配方只跑 compose。

```bash stage:release on:target
DC='{{composeCmd}}'; [ -z "$DC" ] && DC='docker compose'; $DC version >/dev/null 2>&1 || { docker compose version >/dev/null 2>&1 && DC='docker compose' || DC='docker-compose'; }
cd {{deployRoot}} || { echo "❌ 目录不存在：{{deployRoot}}"; exit 1; }
# 注意不能用 `ls a b c d`：ls 只要任一参数缺失就返回非 0，文件存在也会误报「缺失」
[ -f docker-compose.yml ] || [ -f docker-compose.yaml ] || [ -f compose.yml ] || [ -f compose.yaml ] || { echo "❌ {{deployRoot}}/ 下缺 docker-compose.yml —— 请先把 compose 文件放上去（Reeve SFTP/工作台/scp），或在部署目标里开启「Reeve 托管 compose 机密」让 Reeve 自动生成"; exit 1; }
($DC pull {{service}} 2>/dev/null || true)
# docker-compose v1.29.2 重建已存在容器时会读旧容器 image_config['ContainerConfig']，
# 而新版 Docker 的 image inspect 已无此字段 → KeyError: 'ContainerConfig'。
# 先 stop+rm 旧容器（-s 停 -f 强制；不带 -v 故保留数据卷）再 up，走「新建」而非「重建」路径绕过该 bug。
# 本地 docker load 的镜像（image 模式）不在 registry，pull 失败已被 2>/dev/null||true 吞掉，up 用本地镜像起。
$DC rm -fs {{service}} 2>/dev/null || true
$DC up -d {{service}}
```

```bash stage:health on:target
DC='{{composeCmd}}'; [ -z "$DC" ] && DC='docker compose'; $DC version >/dev/null 2>&1 || { docker compose version >/dev/null 2>&1 && DC='docker compose' || DC='docker-compose'; }
cd {{deployRoot}} && $DC ps {{service}} | grep -qE 'Up|running|healthy'
```

```bash stage:rollback on:target
# 简化回滚：重新拉起上一组（更稳妥的做法是固定镜像 tag 后切回旧 tag）
DC='{{composeCmd}}'; [ -z "$DC" ] && DC='docker compose'; $DC version >/dev/null 2>&1 || { docker compose version >/dev/null 2>&1 && DC='docker compose' || DC='docker-compose'; }
cd {{deployRoot}} && $DC up -d {{service}}
```
