ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Docker 容器中运行 AI CLI 工具:TaoToken 用户隔离与持久化卷实战指南

Docker 容器中运行 AI CLI 工具:TaoToken 用户隔离与持久化卷实战指南 1. 为什么要在 Docker 里跑 AI CLI以及多用户场景下最容易踩的坑AI CLI 工具比如各类 coding agent、命令行对话客户端本质上是「本地进程 配置文件 登录态」的组合。你直接在宿主机上装一份自己用没问题但一旦变成多人共享一台开发机、或者放进 CI 流水线里跑问题就来了A 同事的 API Key 和 B 同事的会话历史混在同一个~/.config目录里谁改了配置大家都受影响CI 每次跑完容器一销毁登录态和自定义配置全没了下次还得重新配一遍。Docker 容器中运行 AI CLI 工具核心要解决的就是两件事用户隔离和持久化卷。用户隔离指的是每个用户或每个 CI Job有自己独立的配置目录、独立的 Key、独立的会话状态互不污染持久化卷指的是把配置目录和登录态挂到宿主机或命名卷上容器重建后配置和登录态不丢失。这篇就围绕这两个目标交付一套可以直接复制的 Dockerfile、docker-compose.yml 和 config.toml 骨架并且用 TaoToken 作为统一的 Key/API 通道让多用户共享宿主机时不用每人维护一套上游地址。适合谁看需要在共享开发机、内网 CI、或者团队沙箱环境里跑 AI CLI 的工程师。下面从环境准备开始一步步把可运行的配置搭出来。2. TaoToken 前置准备统一 Key 与 API 通道在容器里跑 AI CLI最烦的是每个用户各自配一套上游地址和 Key容器里环境变量一多就容易乱。TaoToken 在这里的角色是提供一个统一的 API 通道你只需要在平台侧生成 Key容器里通过环境变量注入AI CLI 的 config 里把 base_url 指向 TaoToken 的 API 地址即可。这样多用户共享宿主机时隔离的是「每个用户自己的 Key」而通道是统一的运维成本低很多。先做前置准备。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册并登录然后进入控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建项目。接着到 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 生成一个 Key建议按用户或按 CI Job 分别生成方便后续隔离和吊销。生成后先别急着写 Dockerfile本地用 curl 验证一下 Key 是否可用避免后面在容器里排查网络问题。API 基础地址是 https://taotoken.net/api这个地址不加 UTM 参数直接用于程序调用。验证命令如下curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ | head -c 500如果返回模型列表的 JSON说明 Key 和通道都正常。这里有个细节很多 AI CLI 工具读取的是OPENAI_API_KEY或OPENAI_BASE_URL这类环境变量所以容器里我们统一用TAOTOKEN_API_KEY注入再在 entrypoint 里映射成工具需要的变量名这样 Key 的来源只有一个不会散落在多个配置文件里。注意Key 不要写进镜像层。用--build-arg传 Key 会在镜像历史里留下痕迹正确做法是运行时通过环境变量或 Docker secret 注入。下面 compose 里用的是 env_file生产环境建议换成 secret。3. 可复制的 Dockerfile 与目录结构先规划目录结构。我们用一个ai-cli工作目录里面放 Dockerfile、compose 文件、每个用户的配置模板。核心思路是镜像里只装工具和默认配置骨架用户的实际配置和登录态通过卷挂载进来容器本身无状态。ai-cli/ ├── Dockerfile ├── docker-compose.yml ├── entrypoint.sh ├── config/ │ └── config.toml.tpl └── users/ ├── alice/ │ └── .config/ └── bob/ └── .config/Dockerfile 用多阶段没必要单阶段即可重点是创建一个非 root 用户并把配置目录设为可挂载点FROM node:20-slim # 安装 AI CLI 工具这里以 npm 包为例按你实际工具替换 RUN npm install -g your-org/ai-clilatest # 创建非 root 用户UID 与宿主机用户对齐避免挂载卷权限问题 ARG USER_UID1000 ARG USER_GID1000 RUN groupadd -g ${USER_GID} aiuser \ useradd -m -u ${USER_UID} -g ${USER_GID} -s /bin/bash aiuser # 配置目录作为挂载点 RUN mkdir -p /home/aiuser/.config/ai-cli \ chown -R aiuser:aiuser /home/aiuser/.config COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod x /usr/local/bin/entrypoint.sh USER aiuser WORKDIR /workspace ENTRYPOINT [/usr/local/bin/entrypoint.sh] CMD [ai-cli, --help]entrypoint.sh 负责把统一的TAOTOKEN_API_KEY映射成工具需要的变量并在配置不存在时从模板生成#!/bin/bash set -e CONFIG_DIR/home/aiuser/.config/ai-cli CONFIG_FILE${CONFIG_DIR}/config.toml # 首次启动时从模板生成配置 if [ ! -f ${CONFIG_FILE} ]; then mkdir -p ${CONFIG_DIR} sed s|__API_BASE__|${TAOTOKEN_API_BASE:-https://taotoken.net/api}|g \ /opt/ai-cli/config.toml.tpl ${CONFIG_FILE} fi # 映射成工具识别的环境变量 export OPENAI_API_KEY${TAOTOKEN_API_KEY} export OPENAI_BASE_URL${TAOTOKEN_API_BASE:-https://taotoken.net/api} exec $config.toml 模板骨架关键是 base_url 指向 TaoToken 的 API 地址Key 不写死在文件里由环境变量注入# config.toml.tpl [api] base_url __API_BASE__ # api_key 从环境变量 OPENAI_API_KEY 读取不落盘 [model] default gpt-4o-mini timeout_seconds 60 [history] # 会话历史持久化到挂载卷容器重建不丢 persist true path /home/aiuser/.config/ai-cli/history这里的设计要点base_url用占位符在 entrypoint 里替换这样同一份模板可以适配不同环境history.path指向挂载卷内的路径保证会话历史持久化。镜像里不包含任何 Key符合前面说的安全原则。4. docker-compose 实现用户隔离与持久化卷用户隔离的核心是「每个用户一个容器实例各自挂载自己的配置目录」。docker-compose 里用不同的 service 或者用同一个 service 加 profile 都可以这里用两个 service 演示 alice 和 bob 的隔离version: 3.9 x-ai-cli-common: ai-cli-common build: context: . args: USER_UID: 1000 USER_GID: 1000 environment: - TAOTOKEN_API_BASEhttps://taotoken.net/api volumes: - ./config/config.toml.tpl:/opt/ai-cli/config.toml.tpl:ro working_dir: /workspace services: ai-cli-alice: : *ai-cli-common container_name: ai-cli-alice env_file: - ./users/alice/.env volumes: - ./config/config.toml.tpl:/opt/ai-cli/config.toml.tpl:ro - ./users/alice/.config:/home/aiuser/.config/ai-cli - ./workspace/alice:/workspace stdin_open: true tty: true ai-cli-bob: : *ai-cli-common container_name: ai-cli-bob env_file: - ./users/bob/.env volumes: - ./config/config.toml.tpl:/opt/ai-cli/config.toml.tpl:ro - ./users/bob/.config:/home/aiuser/.config/ai-cli - ./workspace/bob:/workspace stdin_open: true tty: true每个用户的.env文件里只放自己的 Key# users/alice/.env TAOTOKEN_API_KEYsk-alice-xxxxxxxx这样 alice 和 bob 的配置目录、工作目录、Key 全部隔离互不影响。持久化卷用的是 bind mount把宿主机的./users/alice/.config挂进容器容器删了重建配置和历史还在。如果是在 CI 场景不需要长期保留可以用命名卷让 Docker 管理生命周期volumes: ai-cli-ci-cache: driver: local services: ai-cli-ci: : *ai-cli-common env_file: - ./.env.ci volumes: - ai-cli-ci-cache:/home/aiuser/.config/ai-cli - ./:/workspace命名卷的好处是 CI 里可以跨 Job 复用缓存又不会污染宿主机目录。实测下来bind mount 适合开发机多用户命名卷适合 CI。注意挂载宿主机目录时UID/GID 要对齐。如果宿主机用户 UID 是 1001构建时把USER_UID改成 1001否则容器内写文件会报权限错误。这是最常见的坑之一。5. 验证请求与持久化容器重建后配置不丢配置搭好后先验证请求能通。启动 alice 的容器docker compose up -d ai-cli-alice docker compose exec ai-cli-alice bash进容器后确认环境变量和配置echo $OPENAI_BASE_URL cat /home/aiuser/.config/ai-cli/config.toml然后跑一次实际请求用工具自带的命令或直接 curlcurl -s ${OPENAI_BASE_URL}/v1/chat/completions \ -H Authorization: Bearer ${OPENAI_API_KEY} \ -H Content-Type: application/json \ -d { model: gpt-4o-mini, messages: [{role: user, content: ping}] } | head -c 300返回带choices的 JSON 就说明通道正常。接着验证持久化在容器里改一下配置比如把默认模型改掉然后退出并删除容器再重建# 容器内修改配置 sed -i s/gpt-4o-mini/gpt-4o/ /home/aiuser/.config/ai-cli/config.toml # 退出后删除容器 exit docker compose rm -f ai-cli-alice docker compose up -d ai-cli-alice # 重新进入确认修改还在 docker compose exec ai-cli-alice grep default /home/aiuser/.config/ai-cli/config.toml如果输出还是gpt-4o说明配置持久化成功。会话历史同理跑一次对话后检查history目录里有没有文件生成重建容器后再看文件是否还在。这一步是整套方案的关键验证动作别跳过。对于登录态如果你的 AI CLI 工具有独立的登录命令比如ai-cli login登录后凭证一般写在配置目录里只要配置目录挂载了登录态就不会丢。验证方式和上面一样登录一次重建容器再跑命令看是否需要重新登录。6. 本篇常见错误排查权限错误Permission denied。最常见原因是容器内 UID 和宿主机挂载目录的 owner 不一致。解决ls -n ./users/alice/.config看宿主机目录的 UID构建时把USER_UID设成一样的值或者chown -R 1000:1000 ./users/alice/.config。配置没生成config.toml 不存在。检查 entrypoint.sh 是否有执行权限以及模板路径/opt/ai-cli/config.toml.tpl是否挂载正确。可以在 entrypoint 里加set -x临时看执行过程。请求 401Key 无效。先确认.env文件里的 Key 没有多余空格或换行再确认OPENAI_API_KEY在容器内是否正确导出。用docker compose exec ai-cli-alice env | grep API检查。请求 404 或连接超时。检查OPENAI_BASE_URL是否指向https://taotoken.net/api注意结尾不要多加/v1因为工具通常自己会拼/v1/chat/completions。如果工具要求 base_url 带/v1按工具文档调整。容器重建后配置丢失。说明挂载路径写错了或者用了匿名卷。用docker inspect ai-cli-alice | grep -A5 Mounts确认挂载点是否指向宿主机目录。多用户互相看到对方历史。检查两个 service 的 volumes 是否指向了不同目录别共用同一个.config路径。7. 下一步按场景选择接入方式配置跑通后根据你的场景选下一步。如果你是在排查接入问题、需要重新生成 Key 或查看接入文档直接去 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 和接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 对照检查。如果你只是想快速验证某个模型在容器里的表现用模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 直接试不用改容器配置。如果你是长期在容器里跑 coding agent、需要稳定的额度和更长的会话建议看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite配合本文的持久化卷方案容器重建后额度、配置、登录态都不受影响。Claude Code 用户可以参考 Anthropic 接入页 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude-code-anthropicutm_campaignrewrite 调整对应的环境变量映射。最后提醒一句生产环境别把 Key 写进镜像或 compose 文件用 Docker secret 或运行时注入挂载卷的备份策略也要提前想好尤其是 CI 里用命名卷的场景卷删了缓存就没了。
返回列表