Docker 与容器
在 Docker、Podman、Kubernetes 或任何 OCI 运行时中运行 ZeroClaw。
官方镜像
在每次稳定版本发布时推送到 GitHub Container Registry (ghcr.io):
ghcr.io/zeroclaw-labs/zeroclaw:latest:最新稳定版ghcr.io/zeroclaw-labs/zeroclaw:v0.7.5:已固定ghcr.io/zeroclaw-labs/zeroclaw:debian:基于 Debian 的镜像(体积更大,对 glibc 支持更广泛)
多架构:linux/amd64、linux/arm64。
关于 shell 访问的说明: 默认的
latest镜像有意采用 distroless 设计,不包含sh、ash或bash。如果你需要在容器内使用 shell(例如,运行docker exec进行调试),请使用debian标签。
Alpine 镜像(本地构建)
Dockerfile.alpine 构建一个可选启用的 Alpine 镜像,其中包含为 linux/amd64 和 linux/arm64 静态链接的 musl 二进制文件。它不会发布到 ghcr.io。
对于本地平台:
sh
docker build -f Dockerfile.alpine -t zeroclaw:alpine .
对于多平台镜像仓库镜像,请创建一次构建器并推送清单。如果已经选择了 buildx 构建器,则省略第一条命令:
sh
docker buildx create --use --name zeroclaw-multiarch
docker buildx build -f Dockerfile.alpine \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/zeroclaw:alpine \
--push .
内置的 Compose 示例会为当前平台构建镜像:
sh
docker compose -f docker-compose.yml -f docker-compose.alpine.yml up --build
Alpine 镜像使用与现有镜像相同的 /zeroclaw-data 挂载、schema-mirror 环境变量、仪表板路径和网关端口。
最小运行
sh
docker run -d \
--name zeroclaw \
-v zeroclaw-data:/zeroclaw-data \
-p 42617:42617 \
ghcr.io/zeroclaw-labs/zeroclaw:latest
官方镜像已在默认配置中内置了对 [::] 的绑定,并设置了 allow_public_bind = true 和 require_pairing = false,因此这个直接使用 docker run 的示例开箱即用即可访问。下面的 Compose 示例仍会固定这两个网关绑定设置,以免持久化配置或自定义配置悄然恢复为仅监听回环地址。
镜像需要在 /zeroclaw-data 处持久化保存状态。首次运行时,它会引导生成一个默认配置:但你仍需运行 quickstart 后它才能正常使用:
sh
docker exec -it zeroclaw zeroclaw quickstart
运行 zerocode(TUI)
该镜像随 zerocode 终端界面一同提供 zeroclaw 二进制文件。默认入口点是 zeroclaw,因此请通过使用 --entrypoint zerocode 覆盖入口点,并指定交互式 TTY(-it)来启动 zerocode。两个已发布的镜像变体都包含它:
distroless(:latest)
docker run -it --entrypoint zerocode ghcr.io/zeroclaw-labs/zeroclaw:latest
debian
docker run -it --entrypoint zerocode ghcr.io/zeroclaw-labs/zeroclaw:debian
zerocode 连接到正在运行的 ZeroClaw 守护进程,因此请将其指向某个守护进程:
- 同一容器的守护进程: 在已运行守护进程的容器中执行它(
docker exec -it zeroclaw zerocode),它会通过本地 IPC 套接字连接到守护进程。 - 远程守护进程: 使用
zerocode --connect wss://<host>:<port>通过 WebSocket Secure 进行连接;参见远程设置 (WSS)。这是从你自己的终端驱动容器化或远程守护进程的可移植方式。
持久化 /zeroclaw-data(如 Minimum run 所示),以确保 zerocode 读取的配置和身份与守护进程所使用的一致。
组成
一个最小的 docker-compose.yml:
服务:
zeroclaw:
图像: ghcr.io/zeroclaw-labs/zeroclaw:latest
重启: 除非停止
端口:
- "127.0.0.1:42617:42617" # 网关,仅限主机回环
volumes:
- ./data:/zeroclaw-data
环境:
# host 选择容器接口;allow_public_bind 确认非回环监听器,并抑制启动警告。
- ZEROCLAW_gateway__host=0.0.0.0
- ZEROCLAW_gateway__allow_public_bind=true
容器启动后,运行 quickstart:
sh
docker compose exec zeroclaw zeroclaw quickstart
Compose 应显式设置 ZEROCLAW_gateway__host 和 ZEROCLAW_gateway__allow_public_bind。发布端口并不会使容器内绑定到 127.0.0.1 的网关可访问,而 allow_public_bind = true 只表示允许公开绑定,并不会选择具体的绑定地址。将这两个覆盖项放在一起,还能让带有 localhost 默认值的现有卷或自定义配置保持一致的行为。
这会改变暴露范围,因此示例会发布到主机回环地址。这里涉及两个相互独立的边界,但只有其中一个会被强制执行:
gateway.host = 0.0.0.0选择容器内的接口。Docker 网桥流量不会通过容器回环接口到达,因此必须保持为0.0.0.0,已发布的端口才能访问网关。ZEROCLAW_gateway__allow_public_bind是确认项,而不是门控开关。当其为false时,网关会记录启动警告,但仍会进行绑定;将其设置为true只会抑制该警告。不要依赖它来确保监听器保持私有。- Compose 的
ports:映射是 Docker 实际强制执行的边界。"127.0.0.1:42617:42617"仅发布到容器主机;"42617:42617"会发布到 Docker 所配置的每个主机接口。
身份验证边界是 ZEROCLAW_gateway__require_pairing;在架构中其默认值为 true,但在镜像的预置配置中为 false。禁用配对后,网关会响应通过 /webhook、/api/config、/api/memory、/api/browse 以及会话端点发起的未经身份验证的请求。要为其他主机提供服务,请删除 127.0.0.1: 前缀,and 启用配对功能,或者将网关置于需要身份验证的反向代理或隧道之后。
使用 Debian 镜像的无 root Compose
对于需要在容器内使用 shell 工具的无 root Docker 或 Podman Compose 部署,请使用当前的 Debian 镜像并绑定主机数据目录:
服务:
zeroclaw:
图像: ghcr.io/zeroclaw-labs/zeroclaw:debian
container_name: zeroclaw
重启: 除非停止
端口:
- "127.0.0.1:42617:42617"
卷:
- ./data:/zeroclaw-data
环境:
- ZEROCLAW_gateway__host=0.0.0.0
- ZEROCLAW_gateway__allow_public_bind=true
健康检查:
test: [CMD, zeroclaw, 状态, --format=exit-code]
interval: 60s
超时: 10秒
retries: 3
start_period: 10秒
当前 Debian 镜像会将打包的仪表板放置在 /zeroclaw-data 之外,因此绑定挂载不会将其遮蔽,也不需要设置 gateway.web_dist_dir 覆盖项。网关覆盖项使用 schema-mirror 中所示的拼写,即 ZEROCLAW_gateway__host 和 ZEROCLAW_gateway__allow_public_bind。它们的优先级高于已持久化的 localhost 默认配置,而限定于回环地址的 ports: 映射仍是限制主机侧可达范围的边界。
macOS:OrbStack 与 Colima
macOS 没有原生的 Linux 内核,因此每个选项(Docker Desktop、Podman、OrbStack、Colima)都在轻量级 Linux VM 中运行容器。对于 Mac 开发机而言,值得比较的两个 Mac 原生 VM 是 OrbStack 和 Colima,二者都使用上述相同的 docker run/Compose 命令运行容器。
| OrbStack | Colima | |
|---|---|---|
| 引擎 | 自定义、调优的 Linux 虚拟机(针对 Apple Silicon 优化) | Lima VM + containerd/Docker |
| 许可证 | 商业、freemium(个人使用免费) | MIT(底层的 Lima 采用 Apache 2.0) |
| 接口 | 图形界面应用 + 命令行界面 | 以 CLI 为先(colima start/stop),可编写脚本 |
| 最佳适用场景 | 极简操作,精致的用户体验 | 一切皆开源,配置即代码 |
OrbStack
# 提供 docker CLI:
brew install --cask orbstack
Colima
# docker CLI 与 colima 的虚拟机通信:
brew install colima docker docker-compose # docker-compose = Compose v2 插件;如果你需要 `docker compose`,请安装
colima start --cpu 4 --memory 8 # 添加 --network-address 以将虚拟机 IP 暴露给 macOS
对于典型的开发工作负载,二者性能相当;真正的区别在于许可(商业 vs OSS)和使用体验偏好,而非纯粹的速度;如果你在意空闲内存占用或构建吞吐量,请在自己的机器上对两者分别进行基准测试。无论哪种方式,你都是通过 docker 来驱动虚拟机内的引擎;systemd quadlets(见下文)是 Linux 主机的特性,在 macOS 上不适用。
Podman 与 systemd quadlets
在 Linux 服务器上,长期运行容器最简洁的方式是使用 Podman quadlet:一种声明式的单元文件,systemd 会将其转换为真正的服务。你可以获得 systemctl 生命周期管理、journald 日志、自动重启和启动顺序控制,无需守护进程,也无需 --restart 这种取巧手段,而且该单元文件就是可以提交到 git 的配置。这是推荐的服务器模式;docker run/Compose 用于笔记本电脑则完全没问题。
quadlet 是一个 *.container 文件(同类文件还有:.pod、.volume、.network、.kube、.build、.image)。Podman 的 systemd 生成器会在每次 daemon-reload 时读取它,并写入一个临时的 .service;你无需自己编写 .service。
Rootful 单元位于 /etc/containers/systemd/;rootless 单元位于 ~/.config/containers/systemd/。
/etc/containers/systemd/zeroclaw.container:
[Unit]
Description=ZeroClaw agent runtime
After=network-online.target
Wants=network-online.target
[Container]
# Pin a release in production; :latest is distroless (no shell — use :debian to exec a shell).
Image=ghcr.io/zeroclaw-labs/zeroclaw:latest
ContainerName=zeroclaw
PublishPort=127.0.0.1:42617:42617
Volume=zeroclaw-data:/zeroclaw-data
# Published on host loopback only; drop the 127.0.0.1: prefix to serve other
# hosts, and enable pairing or a tunnel before you do. If you mount a
# localhost-default config, override both gateway.host and
# gateway.allow_public_bind together.
# Optional rolling-upgrade path — re-pull a newer image on (re)start and opt into `podman auto-update`:
Pull=newer
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=multi-user.target default.target
部署(幂等操作,可安全地重新运行;重新应用会使运行中的容器收敛到目标状态,而不会重复创建):
sh
sudo cp zeroclaw.container /etc/containers/systemd/
sudo systemctl daemon-reload # 生成器将 .container 转换为 zeroclaw.service
sudo systemctl restart zeroclaw
然后完成一次接入设置,即可像管理任何服务一样管理它:
sh
sudo podman exec -it zeroclaw zeroclaw quickstart
systemctl status zeroclaw
journalctl -u zeroclaw -f
生成的单元没有 systemctl enable 步骤:[Install] WantedBy= 这一行才是让它在开机时启动的关键。
- 版本固定 vs
:latest。 固定标签或摘要(Image=ghcr.io/zeroclaw-labs/zeroclaw:v0.7.5或...@sha256:...)可实现可复现、可审计的部署;这样升级就成为在已提交的.container文件中可审查的标签变更。而Pull=newer+AutoUpdate=registry则由podman-auto-update.timer(sudo systemctl enable --now podman-auto-update.timer)驱动,实现滚动升级。在可复现性与时效性之间二选一;两种方式的部署流程都是相同的。 - Rootless 变体。 将文件放入
~/.config/containers/systemd/,使用systemctl --user daemon-reload && systemctl --user restart zeroclaw,并运行loginctl enable-linger $USER使其在注销后仍然存活(与服务与守护进程中的 lingering 说明相同)。 - WSL2。 现代 WSL2 运行 systemd(在
/etc/wsl.conf中设置[boot] systemd=true,然后执行wsl --shutdown),因此这个完全相同的 quadlet 模式可以在 WSL 发行版内部使用:无需 Windows 专用方言。
容器内的配置
该镜像预期配置位于 /zeroclaw-data/.zeroclaw/ 下。请将本地配置挂载到:
sh
docker run -d --name zeroclaw \
-v $(pwd)/my-config.toml:/zeroclaw-data/.zeroclaw/config.toml:ro \
-v zeroclaw-state:/zeroclaw-data/workspace \
-p 42617:42617 \
ghcr.io/zeroclaw-labs/zeroclaw:latest
对于容器工作负载,请在每个 providers.models.<type>.<alias> 上将 uri 设置为容器可访问的地址(例如,对于 Docker Desktop 主机上的 Ollama 服务器,使用 http://host.docker.internal:11434)。通用的环境变量覆盖机制可以在运行时设置同一字段,而无需编辑配置:
sh
ZEROCLAW_providers__models__ollama__home__uri=http://ollama:11434 zeroclaw agent -a assistant
有关语法,请参阅提供程序 → 容器友好的覆盖配置。
轮询的通道(Telegram、电子邮件):开箱即用
出站发起的通道不需要任何特殊的容器配置。Telegram 轮询、IMAP、MQTT、Nostr 中继:全部采用拉取方式;容器只需要出站网络访问即可。
接收 webhook 的通道:需要入站访问
Discord、Slack、GitHub 以及大多数 webhook 通道需要入站 HTTP。有两种选择:
- 暴露网关:
-p 42617:42617+ 在前端配置带 TLS 的反向代理,将 webhook URL 指向公共地址 - 使用隧道:ngrok、Cloudflare Tunnel 或 Tailscale Funnel;将隧道 URL 设置为 webhook 目标
通过将顶层 [tunnel] 的 tunnel_provider(覆盖环境变量:ZEROCLAW_tunnel__tunnel_provider)设置为受支持的提供商之一,并填写相应的 tunnel.* 配置块来配置隧道;完整的提供商列表及各提供商的字段请参见配置参考。生成的公共 URL 即是你为 webhook 发送方所指向的地址。
Kubernetes
示例 Kubernetes 清单位于 deploy-k8s/ 目录中。典型的清单片段:
apiVersion: apps/v1
类型: 部署
元数据:
名称: zeroclaw
规格:
副本: 1
策略:
类型: 重新创建 # ZeroClaw 每个工作区仅一个实例
模板:
规格:
容器:
- 名称: zeroclaw
图像: ghcr.io/zeroclaw-labs/zeroclaw:v0.7.5
端口:
- 容器端口: 42617
volumeMounts:
- 名称: 数据
挂载路径: /zeroclaw-data
# `containerPort` 不会向主机发布;此处由 Service 或 Ingress 控制暴露。
# 如果挂载了默认使用 localhost 的配置,请同时覆盖 gateway.host 和 gateway.allow_public_bind。
volumes:
- 名称: 数据
持久卷声明:
claimName: zeroclaw-data
扩展性: ZeroClaw 在每个工作区中采用单写入者模式。请勿进行水平扩展;每个代理只运行一个实例。
注销后重新进行身份验证
如果你在容器中运行时退出了 Web UI 的登录状态,现有的配对码将失效。请生成一个新的配对码以重新登录:
sh
docker exec -it zeroclaw zeroclaw gateway get-paircode --new
对于 Compose 部署,请改用 docker compose exec:
sh
docker compose exec zeroclaw zeroclaw gateway get-paircode --new
注意事项
- macOS 主机名怪异行为(Docker Desktop、colima、Rancher Desktop)。 在 macOS 的 Docker Desktop 上,
host.docker.internal开箱即用。在 colima 上,只有当你以colima start --network-address安装时才能访问它(否则容器根本无法看到主机;请通过 VM 的网关 IP 连接,通常为192.168.5.2,或通过共享网络隧道连接)。Rancher Desktop 在近期版本中的行为与 Docker Desktop 类似,但在较旧版本中曾出现host.docker.internal解析失败的问题。如果服务调用因connection refused到host.docker.internal而失败,可用docker run --rm alpine getent hosts host.docker.internal进行验证:输出为空意味着该主机名无法解析,此时你需要使用显式 IP。 - 主机端服务。 如果提供商是主机上的 Ollama,则
uri = "http://host.docker.internal:11434"(位于[providers.models.ollama.<alias>]下)在 Docker Desktop 上可用。在 Linux Docker 上,你可能需要--add-host=host.docker.internal:host-gateway。 - 内存持久化。 Agent 内存(SQLite
brain.db)位于配置目录下的/zeroclaw-data/.zeroclaw/agents/<alias>/workspace/memory/,共享实例数据库位于/zeroclaw-data/data/。挂载/zeroclaw-data可持久化全部内容;若跳过该卷,则每次重启都会丢失对话历史。 - 绑定挂载
/zeroclaw-data。 在/zeroclaw-data上进行主机绑定挂载会替换整个镜像目录,包括默认配置和(此前的)仪表板捆绑包。仪表板现已安装在/usr/share/zeroclawlabs/web/dist,位于挂载点之外,因此绑定挂载不再会将其隐藏。首次运行时,挂载一个空的主机目录,容器会自动引导生成全新的配置;网关会从其镜像路径自动检测仪表板。 - 默认情况下不支持硬件直通。 GPIO / USB 需要显式指定
--device参数(例如--device /dev/ttyUSB0),并且容器用户需要具有dialout/gpio组的匹配 GID。