如何为 Odysseus 启用宿主机 Docker 访问(host-docker overlay 与 DOCKER_GID 配置)
Odysseus 用 Docker Compose 部署后,Cookbook 如果要在本地执行依赖 Docker 守护进程的操作(例如通过 ollama-rocm/ollama-test 容器做 Ollama 模型下载的 docker fallback),会发现容器内虽然装有 Docker CLI,却连不上宿主机的 Docker 守护进程,操作直接失败并提示 “Local Docker daemon access is disabled inside the Odysseus container; a Docker CLI alone is not enough.”。默认 Compose 配置是有意不挂载 /var/run/docker.sock 的,项目提供了官方 overlay 文件 docker/host-docker.yml 作为显式开启项。本文说明如何用它启用宿主机 Docker 访问、DOCKER_GID 该填什么,以及如何确认配置生效。适用前提是:你已经在用 docker compose 运行 Odysseus,并且确实需要让 Cookbook 在容器内管理宿主机 Docker 守护进程。
先了解默认行为与风险边界
在动手之前,确认三件文档中明确写下的事,它们决定了这件事“值不值得做”:
- 默认不挂载 socket。 默认 Docker Compose 有意不挂载
/var/run/docker.sock。如果你只是要连接已有的 Ollama、vLLM 或其他 OpenAI 兼容端点,不需要 Docker socket 访问,不需要启用本 overlay,在 Settings 里直接添加端点即可。 - 这是高信任操作。 文档原文:raw Docker socket access is high-trust,它实际上可以授予对宿主机 Docker 守护进程的广泛控制权;远程服务器的 Docker 工作流(通过 SSH)仍是更推荐的方式。只在你确实需要本地 Docker 守护进程管理时启用。
- 环境变量单独设置无效。 .env.example 中注释明确:
ODYSSEUS_ENABLE_HOST_DOCKER由 overlay 在容器内设置,必须与 socket 挂载成对出现,"setting it alone is not sufficient"。这个变量由 docker/host-docker.yml 自动注入,不需要你手写。
准备:确认宿主机 docker 组的 GID
DOCKER_GID 要求的是宿主机 docker 组的数字 GID。在宿主机上执行:
getent group docker
输出的冒号分隔字段中,第三个数字就是该组的 GID(overlay 注释和 .env.example 中的示例值均为 963,这是 overlay 在未设置 DOCKER_GID 时的回退默认值,但应替换为你宿主机上的真实值)。
另外注意适用对象:本项目 overlay 依赖 COMPOSE_FILE 机制,面向 CLI 用户。如果你用 Portainer、Coolify、Dockhand 这类只接受单个 Compose 文件的栈管理 UI,它们“do not reliably honor COMPOSE_FILE or multiple -f overlays”,本流程不适用,只能保持 CLI 的 COMPOSE_FILE overlay 工作流。
配置 overlay 与 DOCKER_GID
两种方式任选其一(见 docs/setup.md 的 "Host Docker access" 一节):
方式一:写入 .env(推荐,持久生效)。 在仓库根目录的 .env 中添加两行:
COMPOSE_FILE=docker-compose.yml:docker/host-docker.yml
DOCKER_GID=963
其中 DOCKER_GID 替换为上一步查到的宿主机 docker 组 GID;COMPOSE_FILE 按“基础文件在前、overlay 在后”的顺序合并,不要省略 docker-compose.yml 本身。
方式二:在 shell 中导出后再运行 compose。 文档同样支持在运行 docker compose 前导出这两个变量:
export COMPOSE_FILE=docker-compose.yml:docker/host-docker.yml
export DOCKER_GID=963
docker compose up -d
启用后执行:
docker compose up -d
配置变化会使 odysseus 服务被重建。这一步的副作用是容器内的应用短暂重启,宿主机上其他容器不受影响;挂载的是 socket 文件而非整个 /var/run。
overlay 实际做了什么
docker/host-docker.yml 对 odysseus 服务做了三件事:
services:
odysseus:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
group_add: ["${DOCKER_GID:-963}"]
environment:
- ODYSSEUS_ENABLE_HOST_DOCKER=true
- 把宿主机 socket 原路径挂载进容器;
group_add把宿主机 docker 组 GID 加入容器进程的附加组——应用以非 root 用户运行,必须属于该组才能读写 socket,这就是DOCKER_GID存在的意义;未设置时回退到963;- 注入
ODYSSEUS_ENABLE_HOST_DOCKER=true。
应用侧的放行判断(见 src/host_docker_access.py)恰好就是这两个条件同时成立:环境变量为 true,且 /var/run/docker.sock 是一个真实的 socket 文件。overlay 恰好同时提供了两者,缺任何一个,容器内都会继续显示 “Local Docker daemon access is disabled...” 的提示。
docker/entrypoint.sh 的启动脚本还有一段配套的组权限处理:当 ODYSSEUS_ENABLE_HOST_DOCKER=true 且 socket 存在时,entrypoint 会在启动时读取 socket 的 GID,非零时把应用用户加入该组(socket 属组为 0/root 时跳过)。这也说明启用后必须重启容器,让 entrypoint 和新的 group_add 生效。
可选分支:与 GPU overlay 组合
当你确实同时需要 GPU 直通和宿主机 Docker 访问时,文档给出的组合写法是把 GPU overlay 放在 host-docker 之前:
COMPOSE_FILE=docker-compose.yml:docker/gpu.nvidia.yml:docker/host-docker.yml
# 或 AMD:
COMPOSE_FILE=docker-compose.yml:docker/gpu.amd.yml:docker/host-docker.yml
CPU-only 或不需要 GPU 的场景直接用上一条两文件写法即可。
验证是否生效
文档提供的常规检查命令:
docker compose ps
docker compose logs --tail=120 odysseus
确认 odysseus 容器按新配置重建并处于运行状态。
功能层面的判断依据是那个提示信息的消失:启用之前,任何需要本地 Docker 守护进程的 Cookbook 操作都会返回 HOST_DOCKER_ACCESS_HINT(即开头的 "Local Docker daemon access is disabled inside the Odysseus container..." 文案),Cookbook 依赖页的 docker 行也会显示同一段提示;overlay 生效后该放行条件满足,此类操作不再被这条提示拦截。如果你按本文操作后仍看到该提示,检查两点:COMPOSE_FILE 是否包含了 docker/host-docker.yml、DOCKER_GID 是否与宿主机 docker 组 GID 一致(可用 getent group docker 复核)。
限制
- socket 访问是高信任权限,等效于把宿主机 Docker 守护进程的控制权交给容器,文档明确建议远程 SSH 工作流优先。
- 只服务当前场景:连接已有的 Ollama/vLLM/OpenAI 兼容端点不需要本配置,默认部署下这些功能不受影响。
- 栈管理 UI 不可靠地支持
COMPOSE_FILE多文件合并,本方案面向docker composeCLI 用户。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00