想用容器隔离交付 OpenClaw Gateway、又不想在升级夜手工改一堆路径的团队,通常会在 Compose、命名卷与镜像 digest 之间做权衡。本文给出可复现的 Docker 生产路径:与站内 Ubuntu 24.04 + systemd + Tunnel 裸机篇 明确分工,覆盖环境基线、docker-compose.yml 结构、持久化卷、镜像升级与健康检查,以及容器层常见报错的对照表。
裸机篇把抽象层压到最低:进程直接跑在宿主机上,用 systemd 管重启,用隧道承接公网入口。Docker 篇则把交付物从「目录 + Unit」换成「镜像 + Compose」:升级时主要操作是拉取新 digest、滚动容器与核对卷挂载是否仍然有效。两条路都能做到「Gateway 只监听回环、边缘终止 TLS」,差别在于你是否愿意承担镜像供应链与卷治理的复杂度,来换取多环境一致性与回滚粒度。
若团队已经统一了镜像仓库、扫描与 SBOM 流程,Compose 往往是阻力最小的生产形态;若只有单台 VPS、变更频率低,裸机 systemd 可能更省总账。下面六条「痛点拆解」来自常见排障对话,用来帮你判断自己是否准备好上容器。
把 latest 标签当成版本管理:生产应固定 digest 或带构建号的 immutable tag;否则「昨晚还能跑」无法对应到任何一层文件系统。
配置写进镜像层:环境相关参数应走 env、secrets 或挂载只读配置;否则每次改令牌都要重新 build,违背容器交付初衷。
匿名卷堆满磁盘:未命名的缓存卷在多次试验后会悄悄占满 /var/lib/docker;需要命名卷或外部对象存储策略。
健康检查永远返回 200:只检查 HTTP 端口而不验证上游模型或配置加载,会在流量切入后集中爆 502。
compose 与隧道各写各的:ingress 仍指向旧容器 IP 或旧端口时,外网症状与容器日志会完全对不上。
在 Linux 容器里硬扛 macOS 工作负载:与裸机篇同理,需要 Xcode/模拟器的任务应放到远程 Mac 执行层,而不是把容器当万能沙箱。
当你能明确回答「镜像从哪来、卷存什么、升级谁负责」三件事,就可以进入环境与 Compose 模板部分;若答不上来,先在预发布环境把三条答案写成一页纸再动生产。
与裸机路径并行维护时,建议共用同一份监听与隧道拓扑约定:容器内仍只暴露 127.0.0.1 映射到宿主机回环,由 cloudflared 或等价边缘承接。这样从 systemd 迁到 Compose 时,安全边界不需要重写,只替换进程托管层。
若你在团队内同时维护「安装脚本」与「compose 仓库」,务必规定单一事实来源:要么以 compose 为唯一交付入口并在 CI 里渲染出 systemd 片段供少数裸机特例使用,要么反过来——双轨并行时最常见的事故是端口、卷名与 env 文件路径在两边各改一半。
最后提醒:容器能缓解依赖地狱,但不会消除密钥轮换与审计要求。把 env_file 当保险箱而不做权限与轮换流程,和把令牌明文写进仓库本质相同,只是崩溃时间推迟到下次渗透测试。
评审时把「安装分钟数」和「季度升级成本」放在同一行:容器路径的前置投入更高,但每次升级的可重复性也更高。下表用于和干系人对齐,占位服务名与端口请替换为你环境内的真实值。
| 维度 | Gateway 直绑公网 | systemd + 回环 + Tunnel(裸机) | Docker Compose 生产 |
|---|---|---|---|
| 交付单元 | 手工目录与脚本 | Unit + 配置文件 | 镜像 digest + compose 文件 |
| 升级路径 | 高摩擦,易漂移 | 替换二进制与配置,滚动 systemctl | pull 镜像、recreate 容器、核对卷 |
| 隔离性 | 弱 | 中等(依赖用户与权限) | 强(命名空间与 cgroup,仍非完整虚拟化) |
| 可观测性 | 需自建 | journald 清晰 | 需统一 docker logs / 旁路 agent |
| 典型代价 | 安全风险最高 | 运维脚本化要求适中 | 镜像供应链与卷治理成本 |
Compose 的价值在于把「运行态 + 持久化 + 依赖边」声明化;若你拒绝给卷和标签起名字,容器只会把混乱延迟到磁盘告警那天。
以 Ubuntu 24.04 LTS 或同类服务器为例:请安装官方文档支持的 Docker Engine 与 Compose v2 插件(docker compose 子命令),避免混用已废弃的独立 docker-compose 二进制造成 CI 与生产不一致。资源方面,除 Gateway 自身内存外,要为日志、临时解压与并发连接预留 headroom;磁盘分区建议单独关注 /var/lib/docker 的增长曲线。
安全基线与裸机篇一致:业务端口不对公网监听,SSH 仅密钥,防火墙默认拒绝入站。容器只是多了一层命名空间,不会自动替你做好 TLS 与访问控制。
校验版本:docker version 与 docker compose version 输出写入 Runbook,生产与预发布 minor 对齐。
启用 log-driver 与轮转策略:默认 json-file 时配置 max-size / max-file,避免单容器刷爆磁盘。
创建专用网络:在 compose 中声明自定义 bridge,限制仅网关与隧道侧车互通,减少默认 bridge 的意外暴露。
拉取策略与镜像源:记录 registry、镜像名与 digest;生产拉取使用同一镜像仓,避免「调试时 docker.io、上线时私有仓」混用。
准备命名卷或绑定挂载策略:配置与密钥分卷:只读挂载配置目录,可写卷仅放运行态与缓存,密钥用 secret 文件权限 400。
预演一次完整 down/up:在预发布执行 docker compose down 再 up -d,确认卷未丢、隧道仍指向上游。
提示:OpenClaw 具体镜像名、环境变量与启动参数以官方文档为准;下文 YAML 中的服务名、镜像占位与环境键均为示例,落地前请替换并删除未使用字段。
生产映射建议采用 127.0.0.1:宿主机端口:容器端口,让宿主机回环承接隧道上游,与裸机篇「只监听 127.0.0.1」一致。健康检查应至少验证 HTTP 就绪;若官方提供配置校验子命令,可在 start_period 内放宽重试间隔,避免镜像刚起就被误杀。
services:
openclaw-gateway:
image: ghcr.io/example/openclaw-gateway@sha256:<DIGEST>
restart: unless-stopped
env_file:
- ./gateway.env
volumes:
- openclaw_data:/var/lib/openclaw
- ./gateway.yaml:/etc/openclaw/gateway.yaml:ro
ports:
- "127.0.0.1:8787:8787"
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8787/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
volumes:
openclaw_data:
升级建议顺序:① 在预发布 docker compose pull 校验 digest;② 备份命名卷内关键数据或导出配置;③ 生产执行 docker compose up -d --no-deps --build(若无 build 则去掉对应标志)并观察健康检查;④ 本机与隧道各 curl 一次;⑤ 确认无异常后再 docker image prune 清理悬空层(慎用,先确认无回滚需求)。
排错时优先看三层:容器日志是否报配置或权限;宿主机 ss -tlnp 是否仍绑定预期回环端口;隧道 ingress 是否仍指向该端口。外网 502 而 curl 127.0.0.1 正常时,不要先怀疑镜像,先核对路由。
对需要「蓝绿」式切换的团队,可以短暂并行起两套 compose project(不同 project name、不同宿主机回环端口),在隧道或内部 LB 上做权重切换;切完务必 docker compose -p old_project down,否则旧容器会继续占用卷锁或后台任务。
若 Gateway 需要访问宿主机上的 Unix socket 或本地模型侧车,优先评估是否真的需要 network_mode: host——它会绕过部分端口映射隔离,应视为高风险开关并在变更单里双人复核。
注意:不要把含 API 密钥的 gateway.env 提交进 Git;CI 构建日志里禁止打印 compose 渲染后的完整环境。卷权限与 UID/GID 映射错误时,常见症状是「健康检查偶发失败」而非直接启动崩溃。
下列条目用于和平台组对齐「容器默认不是免费午餐」的事实;具体数字请用你们监控中的 P95 与磁盘曲线替换占位描述。
监控侧建议为容器增加「重启次数」「不健康持续时间」与「卷使用率」三类告警,而不是只看 CPU;Gateway 类服务往往在磁盘或文件描述符耗尽时才出现雪崩式重启。
/var/lib/docker 的月增量常以数十 GB计;应与卷备份策略一起纳入告警。start_period,再按 RPS 调整。纯 Linux 容器适合承载 OpenClaw 网关、队列与轻量编排,但在 Xcode、模拟器与 Apple Silicon 特性上仍会撞到硬边界:要么持续为兼容层买单,要么把执行层挪到专用 Mac。相比在个人笔记本或临时机器上凑合跑网关——睡眠、更新与权限弹窗会把自动化打成不可预测状态——把需要稳定在线与苹果生态对齐的工作负载放到合同化的远程 Mac 独占节点,同时让 Linux 侧继续用 Docker 或 systemd 托管控制面,失败域更清晰。综合长期排班、磁盘与合规成本,NodeMini 的 Mac Mini 云端租赁通常是更优解:网关留在 VPS 容器里,重活交给可订购的执行节点,团队不必在「错误层级」上反复修补。