Skip to content

构建一个 Kit,让 Claude Code 在你选择的 Linux 基础镜像上运行。你会安装这个智能体,让它能够访问 Anthropic API,并添加模型设置和给团队的说明。构建结果是 v3 工作负载 Kit,你可以在本地运行它,也可以发布给别人使用。换成其他智能体或你组织自己的基础镜像时,可以遵循同样的步骤。

本教程准备的是完整环境,从系统软件包一直到启动智能体的命令。如果你已经有合适的智能体镜像,请参阅 打包已有的智能体镜像。 要把已发布的智能体 Kit 与工具组合起来,请编写 Kit 集合。

如果你刚开始接触 Kit,请阅读编写 Kit,了解你要创建的文件。字段定义见 上游 v3 规范。

准备 Kit 目录 ​

你需要 sbx、带 Buildx 的 Docker,以及一个 Anthropic API 密钥。在你希望智能体工作的项目旁边创建一个目录:

console
$ mkdir claude-team

完成后的目录包含三个文件:

text
claude-team/
├── claude-team.yaml
├── claude-team.dockerfile
└── context.md

Dockerfile 安装智能体并设置运行它的命令。称为描述符的 YAML 文件告诉 Docker Sandboxes 运行这个智能体需要什么,比如网络访问和凭据。Markdown 文件包含给智能体的说明。让 YAML 文件和 Dockerfile 在扩展名之前使用相同的名字,这样构建才能找到这两个文件。

这个 Kit 使用 v3,独立于内置的 claude Kit。你添加的任何 Mixin 也必须使用 v3。

使用你自己的基础镜像 ​

本教程从 Red Hat Universal Base Image(UBI)9 开始。下面的步骤会添加沙箱所需的工具、用户账户和证书。你可以使用其他 Linux 镜像,包括由你组织维护的镜像。按该镜像调整软件包和账户命令,并遵循同样的 基础镜像要求。

安装系统软件包 ​

创建 claude-team/claude-team.dockerfile,写入基础镜像和软件包:

dockerfile
FROM registry.access.redhat.com/ubi9/ubi:9.8

USER root
RUN dnf install -y bash ca-certificates curl-minimal git shadow-utils tar gzip \
    && dnf clean all

Bash 运行 shell 命令,Git 访问源码仓库,curl 使用 CA 证书发起 HTTPS 请求。其余的软件包用于创建智能体的用户账户并解包它的安装程序。你项目需要的编译器、库或其他工具,也在这里添加。

创建智能体账户 ​

沙箱需要一个 UID 为 1000、主目录为 /home/agent 的非 root agent 用户。把下面内容追加到 Dockerfile,创建该账户以及它的工作区、配置和状态目录:

dockerfile
RUN groupadd --gid 1000 agent \
    && useradd --uid 1000 --gid 1000 --create-home --shell /bin/bash agent \
    && mkdir -p /home/agent/workspace /home/agent/.local/bin \
        /home/agent/.local/share /home/agent/.local/state \
        /home/agent/.config/claude-team /home/agent/.docker/sandbox/locks \
    && chown -R agent:agent /home/agent

在构建期间创建这些目录,可以让智能体在 Docker Sandboxes 挂载工作区和存储之前就成为它们的所有者。在这个示例中智能体运行时没有 sudo,所以系统软件包要在 Dockerfile 中安装。依赖单个沙箱的安装步骤请用 install 钩子。

准备证书信任 ​

沙箱发出的 HTTPS 请求会经过代理。Docker Sandboxes 在启动时会把代理的证书颁发机构(CA)加入沙箱受信任的证书列表。UBI 把证书放在与 sbx 使用的路径不同的位置。把它们复制到预期路径,然后告诉工具使用该文件,这样它们就能同时信任公共证书和代理:

dockerfile
RUN update-ca-trust \
    && mkdir -p /usr/local/share/ca-certificates /etc/ssl/certs \
    && cp /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/certs/ca-certificates.crt

ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
    CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt \
    REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt \
    NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt

如果你在构建期间添加了企业 CA 证书,请在运行 update-ca-trust 和复制证书包之前,把它们放到 /etc/pki/ca-trust/source/anchors/。换成其他发行版时,请使用它自己的证书管理命令和源证书包路径。

准备 shell 环境 ​

在一个 shell 中导出的环境变量不会自动在另一个 shell 中可用。给智能体一个文件,让它可以把变量保存下来供之后的 shell 会话使用。下面的几行创建该文件,并让登录式、交互式和非交互式 Bash shell 都读取它:

dockerfile
RUN touch /etc/sandbox-persistent.sh \
    && chown agent:agent /etc/sandbox-persistent.sh \
    && chmod 0644 /etc/sandbox-persistent.sh \
    && printf '%s\n' '. /etc/sandbox-persistent.sh' \
        > /etc/profile.d/sandbox-persistent.sh \
    && printf '%s\n' '. /etc/sandbox-persistent.sh' >> /home/agent/.bashrc

ENV HOME=/home/agent \
    PATH="/home/agent/.local/bin:${PATH}" \
    BASH_ENV=/etc/sandbox-persistent.sh

BASH_ENV 告诉非交互式 Bash 读取该文件。你会在后面的教程中为智能体加入使用它的说明。

把智能体构建进镜像 ​

把下面内容追加到 Dockerfile,以 agent 身份安装 Claude Code 并设置它的启动命令:

dockerfile
USER agent
ENV CLAUDE_ENV_FILE=/etc/sandbox-persistent.sh \
    IS_SANDBOX=1
ARG CLAUDE_VERSION
RUN curl -fsSL https://claude.ai/install.sh -o /tmp/install-claude.sh \
    && bash /tmp/install-claude.sh "${CLAUDE_VERSION}" \
    && rm /tmp/install-claude.sh

WORKDIR /home/agent/workspace
ENTRYPOINT ["claude", "--settings", "/home/agent/.config/claude-team/settings.json"]
CMD []

以 agent 身份安装,会把 Claude Code 放在 /home/agent/ 下,该用户可以访问它。CLAUDE_ENV_FILE 把 Claude Code 指向你为持久化环境变量准备的文件。你会在下一步的描述符中设置 CLAUDE_VERSION。

Dockerfile 还设置了用户、工作目录、环境变量和启动命令。CMD [] 清除从基础镜像继承的任何参数。--settings 选项会加载你为每个沙箱选择的模型。你会在编写模型设置中创建它的设置文件。

用这个镜像创建的每个沙箱都会得到同一个 Claude Code 二进制文件。接下来的步骤配置 Docker Sandboxes 如何运行它。你添加的任何 Mixin 都必须使用 v3,并且包含与该工作负载的操作系统和架构兼容的工具。

描述工作负载及其输入 ​

创建 claude-team/claude-team.yaml。先标识这个工作负载,并声明两个参数:

  • version 选择在构建镜像时安装的 Claude Code 版本。
  • model 选择创建沙箱时使用的模型。
yaml
# syntax=docker/sandbox-kit:3
schemaVersion: "3"
kind: workload
displayName: Team Claude Code
description: Claude Code with team defaults and API-key authentication

args:
  version:
    default: "2.1.278"
    pattern: '^[0-9]+\.[0-9]+\.[0-9]+$'
    buildArg: CLAUDE_VERSION
  model:
    default: sonnet
    enum: [sonnet, opus, haiku]

provides: ["claude@${{ kit.args.version }}"]

version 设置 Dockerfile 的 CLAUDE_VERSION 构建参数。构建会用 pattern 校验该版本,然后把它写进 provides,让其他 Kit 能核对安装的是哪个 Claude Code 版本。

model 让你在创建每个沙箱时选择模型。这个选择会写进一个设置文件,因此不会改变已安装的智能体。

允许访问 API ​

智能体装好之后,下一步是让它能够访问 Anthropic API。在 claude-team.yaml 的顶层添加一个 capabilities 列表,放在 provides 之后:

yaml
capabilities:
  - type: com.docker.sandbox/sbx@1
  - type: com.docker.sandbox/network-policy@1
    config:
      runtime:
        allow:
          - api.anthropic.com:443

网络规则允许在沙箱运行期间对 Anthropic API 发起 HTTPS 请求。在 Dockerfile 中下载 Claude Code 使用的是构建器的网络,因此这里不需要规则。

sbx@1 条目声明该工作负载已准备好由 sbx 管理智能体的启动。它要求的 shell 和用户账户请参阅 声明智能体启动约定。

声明凭据 ​

Claude Code 能够访问 API,但它还需要完成身份验证。添加一项凭据能力,告诉 Docker Sandboxes 使用哪个密钥以及如何把它放进请求中。密钥会存在你的宿主机上,位于 Kit 之外。

把下面这个条目追加到同一个 capabilities 列表中:

yaml
  - type: com.docker.sandbox/credential@1
    description: Anthropic API access
    config:
      service: anthropic
      phase: runtime
      apiKey:
        name: ANTHROPIC_API_KEY
        proxyManaged: true
        inject:
          - domain: api.anthropic.com
            header: x-api-key
            format: "%s"

沙箱收到的 ANTHROPIC_API_KEY 是一个占位符。当 Claude Code 向 api.anthropic.com 发起请求时,宿主代理会把真正的 API 密钥插入 x-api-key 请求头。密钥始终留在宿主机上。启动该 Kit 时,你会提供它的值并批准使用它。

编写模型设置 ​

Dockerfile 的启动命令会读取 /home/agent/.config/claude-team/settings.json。用生命周期能力创建该文件,并写入为该沙箱选择的模型。

把下面这个条目追加到 capabilities:

yaml
  - type: com.docker.sandbox/lifecycle@1
    config:
      files:
        - path: /home/agent/.config/claude-team/settings.json
          content: |
            {"model": "${{ kit.args.model }}"}
          mode: "0644"

Docker Sandboxes 会填入选中的 model,并在 Claude Code 启动之前写入该文件。在这个时机创建文件,可以让每个沙箱用同一个镜像使用不同的模型。

Docker Sandboxes 在运行完 install 钩子之后,以 UID 1000 写入这些文件。请使用智能体可写的绝对路径,就像这个示例一样。路径中的 $HOME 之类的 shell 变量不会被展开。

添加智能体说明 ​

该 Kit 还可以给 Claude Code 关于环境的说明。把下面的 Markdown 与描述符和 Dockerfile 放在同一目录:

markdown
## Team workflow {#team-workflow}

Read the project's README before changing code. Run the project's checks
before reporting a task complete, and report any checks you couldn't run.

Claude Code is installed in this sandbox. Its additional settings are at
`/home/agent/.config/claude-team/settings.json`.

Use `/etc/sandbox-persistent.sh` for environment exports needed by later
Bash commands. Keep shell completion scripts out of that file because
non-interactive commands also source it.

把一个 agent-context 条目追加到 capabilities,即可包含这些说明:

yaml
  - type: com.docker.sandbox/agent-context@1
    config:
      filename: CLAUDE.md
      contentFile: ./context.md

构建会把 context.md 包含进镜像。沙箱运行时,sbx 会在已挂载工作区的上级目录写入一个 CLAUDE.md 文件。该文件把 Claude Code 指向你的 context.md。你项目中的 CLAUDE.md 仍然留在原处。

像这个示例一样使用 contentFile,可以把较长的说明放在单独的 Markdown 文件中。你也可以用 content 代替 contentFile,直接把说明写在工作负载的描述符里。多个 Kit 的说明如何协同工作,请参阅 运行时访问和说明。

存储密钥并运行 ​

把你的 Anthropic API 密钥存在宿主机上:

console
$ sbx secret set anthropic

在包含 claude-team 的目录中,启动这个 Kit:

console
$ sbx run --name claude-team ./claude-team

sbx 会构建这个 Kit,把你当前的目录作为工作区挂载,然后启动 Claude Code。要在另一个项目上工作,把它的路径追加到命令中。在提示时,批准该 Kit 使用你存储的密钥,然后按 Claude Code 的首次运行提示操作。智能体既需要存储的密钥,也需要你批准使用它。请参阅 凭据绑定。

创建沙箱时可以选择其他模型:

console
$ sbx run --name claude-team-opus ./claude-team \
    --kit-arg claude-team.model=opus

claude-team 前缀与本地 Kit 目录的名字一致。Docker Sandboxes 会检查 opus 属于 enum 中的选项,然后在 Claude Code 启动之前把它写入设置文件。

迭代并发布 ​

编辑描述符、Dockerfile 或上下文文件,然后用不同的名称再创建一个沙箱来测试改动:

console
$ sbx run --name claude-team-test-2 ./claude-team

重启已有沙箱不会应用你的改动。要在本地试用另一个智能体版本,在描述符中更新 args.version.default,然后再创建一个沙箱。

只要本地构建仍然可用,并且源文件和 Kit 参数都没有变化,sbx 就会复用它。未使用的构建可以在七天后被清理,之后再次使用时可能需要恢复或重新构建。 改动源文件或 Kit 参数都可能触发构建,即使像 model 这样只影响沙箱安装的参数也是如此。BuildKit 仍可复用未改变的镜像层。

发布工作负载 ​

Kit 准备好分享后,登录 Docker Hub,然后用 Docker Buildx 构建并推送它。把 <NAMESPACE> 换成你可以推送的 Docker Hub 命名空间:

console
$ docker login
$ docker buildx build ./claude-team \
    --file ./claude-team/claude-team.yaml \
    --tag docker.io/<NAMESPACE>/claude-team:1.0.0 \
    --push

--file 选项告诉 Buildx 读取描述符。它的 syntax 行会选择 Kit 前端,由前端读取配套的 Dockerfile,并把描述符包含进发布的镜像。要发布其他版本的智能体,添加 --build-arg version=<CLAUDE_VERSION>。这个标志使用的是 Kit 参数名 version,描述符把它映射到 Dockerfile 的 CLAUDE_VERSION。

用镜像引用运行已发布的 Kit:

console
$ sbx run --name claude-team-shared docker.io/<NAMESPACE>/claude-team:1.0.0

多平台镜像和分发细节请参阅 构建并分发 Kit。 要把一个工具与它的工作负载分开打包,请参阅 构建工具 Mixin。 该教程同样打包了 Claude Code,所以请把它的 Mixin 与 shell 工作负载一起使用。 把它与本工作负载组合,会得到两个都提供 claude 的 Kit,Docker Sandboxes 会拒绝这种组合。 你也可以把已发布的工作负载放进一个 Kit 集合,并在其中添加设置和说明。工作负载仍然负责定义如何准备基础镜像、安装智能体并启动它。