feat(devcontainer): Add compose-based local devcontainer bootstrap#51
feat(devcontainer): Add compose-based local devcontainer bootstrap#51
Conversation
- Move the librmcs devcontainer setup to docker-compose and generate a local override for host-specific mounts, environment, and workspace path mapping. - Bootstrap shell history and host-matched CLI tools inside the container, and precreate mount targets so local development stays reproducible without committing machine-specific state.
Walkthrough将 VS Code devcontainer 从单镜像配置迁移到 Docker Compose;新增主机探测、生成本地 override、引导容器工具和 Shell 历史同步脚本;在镜像中预建 XDG 目录并调整 .gitignore 与容器级忽略文件。 ChangesDevcontainer 与初始化基础设施整合
序列图sequenceDiagram
participant Host as Host (主机)
participant Init as InitScripts\n(probe & generate)
participant Compose as Docker Compose
participant Container as Dev Container
participant Bootstrap as Bootstrap\n(bootstrap-tools & setup-shell-history)
Host->>Init: 启动 devcontainer 初始化
Init->>Host: 读取环境变量与探测可用工具
Init-->>Init: 写入 .devcontainer/.generated/host-tools.manifest\n并生成 docker-compose.local.override.yml
Init->>Compose: 覆盖文件就位并启动 Compose
Compose->>Container: 启动容器(带挂载与环境)
Container->>Bootstrap: 运行 postCreateCommand
Bootstrap->>Container: 读取 manifest 并通过 npm 安装工具
Bootstrap->>Container: 创建/链接共享 zsh 历史
Container-->>Host: 容器准备就绪,开发环境可用
评估代码审查工作量🎯 3 (中等) | ⏱️ ~25 分钟 可能相关的PR
诗
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.devcontainer/docker-compose.yml (1)
3-3: ⚡ Quick win建议固定镜像版本标签以保证可复现性
使用
latest标签意味着不同时间构建的开发容器可能基于不同镜像,导致环境不一致。建议固定到具体的版本标签或镜像摘要(digest)。♻️ 建议修改
- image: qzhhhi/librmcs-develop:latest + image: qzhhhi/librmcs-develop:<specific-tag> # e.g., v1.2.3 or sha256:...🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.devcontainer/docker-compose.yml at line 3, 当前 docker-compose 中使用了不固定的镜像标签 "image: qzhhhi/librmcs-develop:latest",请将其替换为具体的版本标签或镜像摘要(digest),例如使用 "qzhhhi/librmcs-develop:vX.Y.Z" 或 "qzhhhi/librmcs-develop@sha256:...",以保证开发容器可复现;更新位于文件中声明该镜像的那一行(即包含 "image: qzhhhi/librmcs-develop:latest" 的条目),并在提交说明中注明所选版本号或 digest 来源。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.devcontainer/docker-compose.yml:
- Around line 14-16: Remove the unconditional bind mount of /tmp/.X11-unix from
docker-compose.yml and instead add the mount only when DISPLAY is set inside
generate-local-override.sh so the X11 socket is created/forwarded conditionally;
specifically, delete the bind mount block (type: bind, source: /tmp/.X11-unix,
target: /tmp/.X11-unix) from the compose file and update the script that sets
DISPLAY (generate-local-override.sh) to append an override or runtime mount for
/tmp/.X11-unix when $DISPLAY is non-empty, keeping the mount logic consistent
with the existing conditional export of DISPLAY.
---
Nitpick comments:
In @.devcontainer/docker-compose.yml:
- Line 3: 当前 docker-compose 中使用了不固定的镜像标签 "image:
qzhhhi/librmcs-develop:latest",请将其替换为具体的版本标签或镜像摘要(digest),例如使用
"qzhhhi/librmcs-develop:vX.Y.Z" 或
"qzhhhi/librmcs-develop@sha256:...",以保证开发容器可复现;更新位于文件中声明该镜像的那一行(即包含 "image:
qzhhhi/librmcs-develop:latest" 的条目),并在提交说明中注明所选版本号或 digest 来源。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 596b5da4-7011-418d-871a-8d835556eb9e
📒 Files selected for processing (9)
.devcontainer/.gitignore.devcontainer/devcontainer.json.devcontainer/docker-compose.yml.devcontainer/scripts/bootstrap-tools.sh.devcontainer/scripts/generate-local-override.sh.devcontainer/scripts/probe-host-tools.sh.devcontainer/scripts/setup-shell-history.sh.gitignoreDockerfile
💤 Files with no reviewable changes (1)
- .gitignore
There was a problem hiding this comment.
🧹 Nitpick comments (1)
.devcontainer/scripts/generate-local-override.sh (1)
20-30: 💤 Low value
add_env的 if/else 分支逻辑冗余两个分支的结果完全相同:当
environment_entries为空时,"${environment_entries}content"与"content"等价,因此整个 if/else 可以简化为一行赋值。♻️ 建议简化
add_env() { env_name=$1 env_value=$2 escaped_env_value=$(escape_yaml_double_quoted "$env_value") - - if [ -n "$environment_entries" ]; then - environment_entries="${environment_entries} ${env_name}: \"${escaped_env_value}\"\n" - else - environment_entries=" ${env_name}: \"${escaped_env_value}\"\n" - fi + environment_entries="${environment_entries} ${env_name}: \"${escaped_env_value}\"\n" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.devcontainer/scripts/generate-local-override.sh around lines 20 - 30, The add_env function contains redundant if/else branches that produce identical output; simplify by removing the conditional and always append the new entry to environment_entries in one assignment, e.g. update the body of add_env (which references env_name, env_value, escaped_env_value, and escape_yaml_double_quoted) so it computes escaped_env_value and then does a single line: environment_entries="${environment_entries} ${env_name}: \"${escaped_env_value}\"\n".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In @.devcontainer/scripts/generate-local-override.sh:
- Around line 20-30: The add_env function contains redundant if/else branches
that produce identical output; simplify by removing the conditional and always
append the new entry to environment_entries in one assignment, e.g. update the
body of add_env (which references env_name, env_value, escaped_env_value, and
escape_yaml_double_quoted) so it computes escaped_env_value and then does a
single line: environment_entries="${environment_entries} ${env_name}:
\"${escaped_env_value}\"\n".
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8f11a394-d3bb-444b-9a5a-6c31565151db
📒 Files selected for processing (2)
.devcontainer/docker-compose.yml.devcontainer/scripts/generate-local-override.sh
✅ Files skipped from review due to trivial changes (1)
- .devcontainer/docker-compose.yml
概述
将 librmcs 的 devcontainer 配置从单容器 image 迁移到基于 Docker Compose 的流程,新增主机特定的本地 override 生成、主机工具探测与容器内自举、共享 Zsh 历史,以及预创建挂载目标;旨在提升本地开发的可重现性并将主机特定配置留在本地生成目录中。
核心变更
Docker Compose 与 devcontainer 配置
.devcontainer/docker-compose.yml:新增服务librmcs-develop,使用镜像qzhhhi/librmcs-develop:latest,设置network_mode: host、设备 cgroup 规则c 189:* rw、init: true,并挂载/dev及仓库根目录到容器(工作目录/home/ubuntu),命令保持容器驻留。.devcontainer/devcontainer.json:切换为dockerComposeFile配置,引用docker-compose.yml与生成的.generated/docker-compose.local.override.yml;新增initializeCommand(生成本地 override 并探测主机工具)和postCreateCommand(设置 shell 历史并在容器内自举工具);保留 VS Code 自定义扩展列表与部分设置。本地 override 生成
.devcontainer/scripts/generate-local-override.sh:生成.devcontainer/.generated/docker-compose.local.override.yml,功能包括:HOST_WORKSPACE_FOLDER;/.codex、/.claude、/.config/opencode、/.local/share/... 等),并支持只读挂载(例如~/.agents/skills);主机工具探测与容器内自举
.devcontainer/scripts/probe-host-tools.sh:在宿主机或本地环境中探测codex、claude、opencode、lark-cli的可用性与版本,生成.devcontainer/.generated/host-tools.manifest(记录generated_at与各工具状态:版本 / absent / unparseable)。.devcontainer/scripts/bootstrap-tools.sh:在容器内读取上述 manifest,若存在 npm 则按 manifest 中记录的版本尝试通过sudo npm install -g安装对应包(映射:codex -> @openai/codex, claude -> @anthropic-ai/claude-code, opencode -> opencode-ai, lark-cli -> @larksuite/cli);输出已安装与跳过的汇总,遇到 manifest 不存在、工具缺失或版本不可解析时跳过并记录原因;若容器内无 npm,则优雅退出。Shell 历史与挂载目标预创建
.devcontainer/scripts/setup-shell-history.sh:在仓库内创建共享历史文件.devcontainer/.zsh_history,并将容器用户~/.zsh_history链接到该文件(保证历史共享、避免提交本机历史)。.zsh_history的原始符号链接步骤(历史文件由 setup-shell-history.sh 在运行时处理)。版本控制与忽略规则
.devcontainer/.gitignore:新增忽略规则.zsh_history与.generated/(本地生成产物与历史不纳入版本库)。.gitignore:新增忽略build/和compile_commands.json;此前对.devcontainer/.zsh_history的忽略已调整以配合新的 devcontainer 忽略策略。设计要点与价值