code-server 部署到 Coder 工作区:install.sh 启动脚本、healthz 健康检查与官方模块方案
【免费下载链接】code-serverVS Code in the browser项目地址: https://gitcode.com/GitHub_Trending/co/code-server
本文以 docs/coder.md 为主体,讲解如何在 Coder 工作区的 Terraform 模板中部署 code-server。读完后你可以掌握两套落地方案:一是在coder_agent的startup_script中用官方安装脚本拉起服务,并配置coder_app的/healthz健康检查;二是直接引用官方发布的 Coder 模块。同时会深入源码说明--auth none、--port参数的含义、/healthz端点的真实实现以及心跳(heartbeat)机制如何避免健康检查“误伤”活跃状态判定。
为什么把 code-server 跑在 Coder 工作区里
Coder 的每个 workspace 由一个或多个coder_agent进程负责执行初始化脚本并代理端口。code-server 作为“浏览器中的 VS Code”,只需要在 agent 容器内启动一个监听本地端口的 HTTP 服务,再通过coder_app资源把localhost:13337暴露为工作区应用即可。docs/coder.md给出的正是这条最典型的路径:agent 装服务、app 做路由与探活、Terraform 声明式管理三者。
方案一:startup_script 中用 install.sh 安装并启动
官方推荐在模板中使用仓库根目录提供的 install.sh 脚本。docs/coder.md中的完整模板如下:
resource "coder_agent" "dev" { arch = "amd64" os = "linux" startup_script = <<EOF #!/bin/sh set -x # install and start code-server curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3 code-server --auth none --port 13337 & EOF } resource "coder_app" "code-server" { agent_id = coder_agent.dev.id slug = "code-server" display_name = "code-server" url = "http://localhost:13337/" icon = "/icon/code.svg" subdomain = false share = "owner" healthcheck { url = "http://localhost:13337/healthz" interval = 3 threshold = 10 } }install.sh 的工作方式与--version参数
安装脚本支持--version X.X.X指定固定版本(模板中固定为 4.8.3,保证工作区可复现),也支持--edge安装最新 edge 版。从 install.sh 源码看,其核心行为包括:
- 安装方式选择:
--method detect(默认)会按发行版选择包管理器——Debian/Ubuntu 走 deb 包,Fedora/CentOS/RHEL/openSUSE 走 rpm 包,Arch 走 AUR,FreeBSD/Alpine 走 npm,macOS 优先 Homebrew,其余系统直接从 GitHub Release 拉取;--method standalone则强制把发行包解压到--prefix(默认~/.local)。 - 架构约束:Release 只为 Linux 的 amd64/arm64 和 macOS 的 amd64 构建,detect 模式在无匹配 Release 时会回退到 npm 安装,standalone 模式则会报错。这解释了模板里
coder_agent的arch = "amd64"写法——与工作区架构保持一致才能命中预构建产物。 - 下载缓存:脚本会把所有下载的资产缓存在
~/.cache/code-server,工作区重启时的二次安装会更快。
--auth none与--port 13337:启动参数的源码依据
在 Coder 场景下关闭 code-server 自身的认证是有意为之——访问控制交给 Coder 的 workspace 代理层(share = "owner"表示只有 workspace 属主可访问应用),code-server 不再重复要求密码。参数含义可从源码确认:
--auth:src/node/cli.ts 中定义了AuthType枚举,仅有password与none两个取值;src/node/cli.ts 的setDefaults显示,若不显式指定,默认值是password。因此在 Coder 模板中必须显式写--auth none,否则工作区会多出一层需要密码的登录页。--port:属于已被--bind-addr取代但仍可用的参数(见 src/node/cli.ts 注释 “These two have been deprecated by bindAddr”),--port 13337即监听 13337 端口。也可以用--bind-addr 127.0.0.1:13337或环境变量$PORT覆盖,模板中选用--port是因为它更直观且与coder_app的url一一对应。- 启动命令末尾的
&让 code-server 在后台运行,避免阻塞startup_script中后续可能的步骤。
coder_app 各字段的作用
url = "http://localhost:13337/":Coder 在该 agent 容器内代理此地址,浏览器访问的工作区应用实际由 Coder 路由进来,这也是为什么--auth none是安全可行的。subdomain = false:以路径方式挂载(如/code-server/),而不是独立子域名;对需要 base-path 适配的场景,code-server 本身带有对代理路径的处理补丁(见 patches/base-path.diff)。share = "owner":只有 workspace 属主能打开该应用,弥补了--auth none取消认证后的访问控制缺口。healthcheck:Coder 每隔interval(3 秒)探测一次url,连续threshold(10 次)失败才判定应用不可用。选择/healthz而非根路径不是随意的,原因在于下面的实现细节。
/healthz 端点:源码级的健康检查机制
code-server 的/healthz路由在 src/node/routes/index.ts 中挂载,处理逻辑位于 src/node/routes/health.ts:它返回一个 JSON,包含status(alive或expired)和lastHeartbeat时间戳:
router.get("/", (req, res) => { res.json({ status: req.heart.alive() ? "alive" : "expired", lastHeartbeat: req.heart.lastHeartbeat, }) })而alive()的判定来自心跳模块 src/node/heart.ts:code-server 通过一个本地心跳文件记录活动,heartbeatInterval为 60000 毫秒,alive()的语义是“距上次心跳不足 60 秒”。任何真实用户请求都会触发heart.beat()刷新心跳。
关键的排除逻辑在 src/node/routes/index.ts:
// /healthz|/healthz/ needs to be excluded otherwise health checks will make // it look like code-server is always in use. if (!/^\/healthz\/?$/.test(req.url)) { heart.beat() }即健康检查请求本身不刷新心跳。这样设计的原因可以推断为:Coder 每 3 秒一次的探测如果计入“使用量”,会让status永远是alive,健康检查就失去了反映“用户是否真的在用编辑器”的意义。对部署者而言的实用结论是:当 Coder 报告应用不健康、或你直接curl该端点看到expired时,说明 60 秒内没有任何真实用户活动,这可用于判断空闲工作区;而 HTTP 层探活(进程是否存活、端口是否监听)由 Coder 的interval/threshold机制独立保障。对应行为在单元测试 test/unit/node/routes/health.test.ts 中有覆盖。
方案二:使用官方 Coder 模块
对于不想在模板里手写安装命令的场景,Coder 官方在模块 registry 中发布了 code-server 模块,模板中只需引用:
module "code-server" { source = "registry.coder.com/modules/code-server/coder" version = "1.0.5" agent_id = coder_agent.example.id extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"] }其中extensions参数支持按 VS Code 扩展 ID 批量预装扩展。这一能力对应 code-server CLI 的--install-extension选项:src/node/cli.ts 说明其接受${publisher}.${name}形式的扩展标识符或 vsix 文件,并可追加@${version}指定版本(例如vscode.csharp@1.2.3)。模块本质上就是把“install.sh 安装 + 启动 + coder_app 声明 + 扩展预装”打包成了可版本化管理的 Terraform 组件。
常见问题与求助渠道
- 版本固定:模板示例中
--version 4.8.3是显式钉死的,避免 Coder 重建工作区时因上游发版导致行为漂移;需要升级时应显式改模板,而不是依赖“latest”。 - 端口冲突:
13337只是约定端口,若 agent 容器内已有服务占用,可更换--port并同步修改coder_app.url与healthcheck.url。 - 认证层混淆:若在 Coder 代理的应用地址上仍看到 code-server 自带登录页,说明
--auth none未生效或启动命令被改写;反过来,若绕过 Coder 直接暴露 code-server 端口,则务必恢复密码认证(auth: password,密码仅可通过$PASSWORD/$HASHED_PASSWORD或配置文件传入,见 src/node/cli.ts)。 - 求助渠道:官方文档建议遇到问题时到 Coder 的
coder/coder项目 Discussions 区提问,code-server 与 Coder 同属 Coder 团队维护,该渠道能同时覆盖两侧的问题定位。
小结
在 Coder 工作区部署 code-server 的完整链路是:coder_agent.startup_script通过 install.sh 安装固定版本(detect 模式按发行版选包管理器、无预构建产物时回退 npm),以--auth none --port 13337后台启动;coder_app声明代理地址、属主级共享,并基于/healthz做 3 秒间隔、10 次阈值的健康检查——该端点由 health.ts 提供,且健康检查流量被有意排除在 src/node/routes/index.ts 的心跳刷新之外,从而区分“进程存活”与“真实使用”。更省事的替代方案是引用官方registry.coder.com/modules/code-server/coder模块,通过extensions参数(底层即--install-extension)预装扩展。两条路径均以上述 Terraform 配置为最小可复制起点。
【免费下载链接】code-serverVS Code in the browser项目地址: https://gitcode.com/GitHub_Trending/co/code-server
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考