Podman / Rootless
Podman 沙箱路径使用与 Docker 相同的容器契约,但当选择 sandbox.kind: podman 或
sandbox.engine: podman 时,会把 CLI 解析为 podman。本页介绍何时选择 Podman、rootless 本地配置、
嵌套容器模式、运行时保证、SELinux 注意事项,以及 --storage-driver=overlay 故障恢复要点。
何时选择 Podman
Section titled “何时选择 Podman”当部署环境偏好 rootless、无守护进程的容器,或无法运行特权 Docker 守护进程时,使用 Podman。
AICR 仍然只把受限的审查目录挂载进每个运行容器,并保持 source/ 只读,因此隔离保证与 Docker 路径
完全一致。
Rootless 本地配置
Section titled “Rootless 本地配置”用你的平台包管理器安装 Podman,然后验证服务用户能看到 CLI:
podman --versionpodman run --rm --network none alpine:latest true在 Linux 上,仅当基于 socket 的部署模式需要时,才启用用户 socket:
systemctl --user enable --now podman.socketsystemctl --user status podman.socketrootless socket 路径通常是:
/run/user/$UID/podman/podman.sockAICR 配置
Section titled “AICR 配置”为本地或自托管运行强制使用 Podman:
agent: sandbox: kind: podman engine: podman image: ghcr.io/owent/aicr-agent:latest让 AICR 先探测 Docker,再探测 Podman:
agent: sandbox: kind: docker engine: auto仅当需要提升隔离性或为特定 workspace 选择镜像时,才使用 workspace 覆盖:
workspaces: instances: internal-python: source_repo: { trigger: gitea-internal, repo: owent/example } sandbox: kind: podman engine: podman image: ghcr.io/example/python-review:latest嵌套容器沙箱(AICR 运行在容器内)
Section titled “嵌套容器沙箱(AICR 运行在容器内)”当 AICR 本身运行在容器内(例如通过 deploy.sh),且你希望沙箱为 agent 隔离派生子容器时,必须
把宿主容器引擎的 socket 挂载进 AICR 容器。这是一种应用于 Podman 的 Docker-out-of-Docker(DooD)
模式。
-
必须启用宿主用户级 Podman socket:
Terminal window systemctl --user enable --now podman.socket -
AICR 镜像内有 Podman CLI。运行时镜像内置了
podman,因此sandbox.kind: podman/sandbox.engine: podman能通过CONTAINER_HOST与挂载的宿主 socket 通信。 -
AICR 镜像内有可选的 Docker 静态二进制,用于 Docker 兼容客户端(当
AICR_ENABLE_CONTAINER_SANDBOX=true时由deploy.sh安装)。 -
deploy.sh环境变量:Terminal window AICR_ENABLE_CONTAINER_SANDBOX=true # 启用 socket 挂载 + Podman/Docker 客户端 -
config.yaml沙箱 kind 尽可能设为原生 Podman:agent:sandbox:kind: podmanengine: podman当你确实需要 Docker CLI 语义时,Docker 兼容模式仍然可用:
agent:sandbox:kind: dockerengine: auto
- 运行时镜像安装了
podman、buildah和skopeo。AICR 容器内不启动 Podman 守护进程 — CLI 只是被挂载的宿主 Podman API socket 的客户端。 - 当
AICR_ENABLE_CONTAINER_SANDBOX=true时,deploy.sh会下载 Docker 静态二进制并固化进镜像; 否则它会创建一个无害的空deploy/docker-static占位文件,以保证干净的源码同步仍能满足 Dockerfile 的可选COPY步骤。运行时镜像会移除这个空占位文件,而不是安装一个 0 字节的docker可执行文件。 - 运行时,
deploy.sh把宿主用户级 Podman socket (/run/user/$UID/podman/podman.sock)挂载进 AICR 容器。 deploy.sh设置CONTAINER_HOST=unix:///run/user/$UID/podman/podman.sock,让 Podman CLI 与宿主 Podman 服务通信。deploy.sh还设置DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock,让 Docker 兼容工具能 使用 Podman 的 Docker API 层。--userns=keep-id --group-add keep-groups确保容器进程能访问用户级 socket。- 当挂载了 Podman socket 时,会添加
--security-opt label=disable,这与 Podman 官方文档关于在 SELinux 启用的宿主上从另一个容器内访问 Unix socket 的建议一致。
把 socket 当作特权访问
Podman API 能启动容器,并以拥有该 socket 的宿主用户身份执行任意代码。挂载它就等于把这种控制力 交给了 AICR 容器 — 仅在你完全可控的宿主上这样做。参见 运维与安全。
部署完成后,从 AICR 容器内确认:
podman exec aicr sh -c 'podman --version && podman run --rm alpine:latest echo podman-ok'podman exec aicr sh -c 'docker --version && docker run --rm alpine:latest echo docker-ok'Podman 路径与 Docker 保持相同的沙箱保证:
- 在调用 Podman 之前,会先针对
ALLOWED_COMMANDS检查容器命令。 - 除非显式接入了未来的白名单代理,容器以
--network none运行。 source/以只读方式挂载到/workspace/source。agent/和tmp/是仅有的可写 workspace 挂载。- 临时
--env-file文件创建在挂载的 workspace 目录之外,并在运行后删除。 - 默认不挂载 Docker 和 Podman 宿主 socket。
SELinux 注意事项
Section titled “SELinux 注意事项”在启用了 SELinux 的宿主上,bind mount 可能需要重新打标签。优先使用专用的审查镜像和归服务用户所有 的 workspace 目录。如果宿主要求显式标签,请在后端挂载策略中添加,而不要手工编辑生成的命令。
invalid internal status, try resetting the pause process with "podman system migrate"
Section titled “invalid internal status, try resetting the pause process with "podman system migrate"”当 rootless Podman 的存储驱动初始化失败时会出现此错误 — 常见于系统重启、OOM kill,或
/etc/containers/storage.conf 使用了自定义 rootless_storage_path 之后。
快速修复(非破坏性):
# 显式强制 overlay 驱动 — 绕过损坏的自动探测podman --storage-driver=overlay system migrate
# 重启已停止的容器podman start aicr caddy
# 验证curl -sf http://127.0.0.1:8090/healthz原理: 当 /etc/containers/storage.conf 配置了自定义路径(graphroot、runroot、
rootless_storage_path)时,Podman 5.x 在 rootless 模式下可能无法自动探测存储驱动。显式指定
--storage-driver=overlay 会跳过自动探测,直接打开基于 overlay 的存储。
如果 migrate 仍然崩溃: 检查 /run/user/$UID/libpod/tmp/exits/ 或
/run/user/$UID/libpod/tmp/persist/ 下是否有退出码为 137(SIGKILL)的陈旧容器退出记录。删除这些
文件后再重试 migrate。
在部署脚本中预防: 当 deploy.sh 运行 Podman(默认的 AICR_ENGINE=podman 路径)时,始终指定
--storage-driver=overlay:
podman --storage-driver=overlay build -t aicr:latest ...podman --storage-driver=overlay run -d --name aicr ...如果选择了 AICR_ENGINE=docker,请省略这个 Podman 专属标志,并在 docker ps 无法连接守护进程时
快速失败。
用于自动化的预检:
if ! podman ps >/dev/null 2>&1; then podman --storage-driver=overlay system migratefi其他常见问题
Section titled “其他常见问题”podman --version失败:为服务用户安装 Podman,并确保服务环境中可用PATH。- 容器无法读取
/workspace/source:验证宿主源目录存在,且服务用户有读权限。 - 容器无法写入
/workspace/agent或/workspace/tmp:验证 workspace 归属和 rootless UID 映射。 - 沙箱回退到 native 模式:设置
agent.sandbox.kind: podman和agent.sandbox.engine: podman, 让缺失的 Podman 二进制在预检阶段失败,而不是静默优先使用 Docker。