Dev Containers 本地开发环境怎么给同事复现?VS Code 容器跑通后,用 cpolar 远程验收服务预览

📅 2026/7/14 4:44:27
Dev Containers 本地开发环境怎么给同事复现?VS Code 容器跑通后,用 cpolar 远程验收服务预览
Dev Containers 本地开发环境怎么给同事复现VS Code 容器跑通后用 cpolar 远程验收服务预览团队协作里有一个很常见的卡点代码在我电脑上能跑同事拉下来以后Node 版本、系统依赖、环境变量、端口映射各不一样光是复现开发环境就要耗掉半天。Dev Containers 常用来解决“环境一致性”问题。它把开发环境写进仓库里的.devcontainer配置同事用 VS Code 打开项目后直接进入同一套容器环境。代码、依赖、终端、调试端口都在容器里跑减少“你本机装了什么”的影响。但环境跑通以后还有一步经常被忽略怎么让不在本地的同事快速验收服务页面或接口响应把代码发过去让对方也装 Docker 是一种方式但对于产品、测试、后端联调同事来说临时打开一个可访问的预览地址更高效。这篇就用一个最小 Node.js Web 服务演示完整流程用 VS Code Dev Containers 复现本地开发环境在容器里启动示例服务通过端口映射让宿主机访问容器服务用 cpolar 生成临时 HTTPS 地址让远程同事直接打开验收验收结束后关闭公网入口避免开发服务长期暴露。一、这套方案面向哪些场景可以用于这些场景前端、后端、全栈项目需要统一 Node、Python、Go、Java 等开发环境新同事入组时希望减少本机依赖安装步骤本地功能已经跑通需要让测试或产品同事远程看一眼页面接口文档、Mock 服务、Storybook、Swagger UI、管理后台 Demo 需要临时验收公司网络、家庭宽带、路由器 NAT 导致同事无法直接访问你的本机端口还没到正式部署阶段不想为了一个验收页面申请服务器、域名和证书。边界情况也要说清楚如果这个服务已经面向客户长期使用或者涉及正式账号、支付、用户隐私、生产数据库就应该走正式发布流程。Dev Containers 负责开发环境一致性cpolar 负责临时公网访问入口它们不是生产发布系统。二、最终效果完成后项目目录里会有这样一套最小结构devcontainer-cpolar-demo/ ├── .devcontainer/ │ ├── devcontainer.json │ └── Dockerfile ├── package.json └── server.js本机开发者的操作流程是VS Code 打开项目 - Reopen in Container - 容器内 npm install - 容器内 npm run dev - VS Code 转发 3000 端口到宿主机 - 宿主机浏览器访问 http://localhost:3000 - cpolar 暴露宿主机 3000 端口 - 同事打开 https://xxxx.cpolar.top 验收页面远程同事无需安装 Docker、Node、VS Code也不需要拉代码。对方只需要拿到临时 HTTPS 地址就能看到容器内服务的运行结果。这里有三层端口关系需要提前理清层级地址示例作用容器内服务0.0.0.0:3000Node 服务真实监听的位置宿主机访问http://localhost:3000VS Code / Docker 转发后的本机入口公网验收https://xxxx.cpolar.topcpolar 转发到宿主机 3000 端口后的外部入口开发时只要记住一句话服务在容器内监听0.0.0.0VS Code 把端口转发到宿主机cpolar 再把宿主机端口临时开放给外部访问。三、环境准备本机准备这几个工具Docker Desktop负责运行 Dev ContainerVS Code负责打开项目VS Code 插件 Dev Containers插件标识是ms-vscode-remote.remote-containerscpolar 客户端负责生成临时 HTTPS 公网地址一个可用的 cpolar 账号用于登录客户端和管理隧道。先确认 Docker 可用docker version docker compose version确认 VS Code 已安装 Dev Containers 插件后可以在 VS Code 命令面板里看到Dev Containers: Reopen in Container安装并登录 cpolar 后确认客户端可用cpolar version cpolar authtoken 你的认证 tokenauthtoken只需要配置一次。token 可以在 cpolar 控制台里查看命令里的尖括号不要保留。四、创建最小示例项目新建项目目录mkdir devcontainer-cpolar-demo cd devcontainer-cpolar-demo mkdir .devcontainer创建package.json{ name: devcontainer-cpolar-demo, version: 1.0.0, private: true, type: module, scripts: { dev: node server.js }, dependencies: { fastify/cors: ^9.0.1, fastify: ^4.28.1 }, devDependencies: {} }创建server.jsimport Fastify from fastify; import cors from fastify/cors; const app Fastify({ logger: true, }); await app.register(cors, { origin: true, }); app.get(/, async () { return { name: Dev Containers cpolar demo, status: ok, message: Service is running inside a VS Code Dev Container., time: new Date().toISOString(), }; }); app.get(/health, async () { return { ok: true, uptime: process.uptime(), }; }); app.get(/preview, async () { const html !doctype html html langzh-CN head meta charsetutf-8 / meta nameviewport contentwidthdevice-width, initial-scale1 / titleDev Container Preview/title style body { font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif; margin: 0; background: #f6f7f9; color: #1f2937; } main { max-width: 760px; margin: 64px auto; padding: 0 24px; } section { background: #fff; border: 1px solid #e5e7eb; border-radius: 8px; padding: 28px; } h1 { margin: 0 0 12px; font-size: 28px; } p { line-height: 1.8; } code { background: #eef2ff; padding: 2px 6px; border-radius: 4px; } /style /head body main section h1Dev Container 服务预览页/h1 p这个页面由容器内的 Node.js 服务返回用来给远程同事验收开发环境里的运行结果。/p p健康检查地址code/health/code/p p当前时间${new Date().toISOString()}/p /section /main /body /html; return app .reply .type(text/html; charsetutf-8) .send(html); }); const host 0.0.0.0; const port Number(process.env.PORT || 3000); await app.listen({ host, port });注意这里监听的是0.0.0.0不是127.0.0.1。在容器场景里如果服务只监听容器自己的回环地址端口转发和外部访问很容易失败。五、最小.devcontainer配置创建.devcontainer/DockerfileFROM mcr.microsoft.com/devcontainers/javascript-node:1-22-bookworm WORKDIR /workspace创建.devcontainer/devcontainer.json{ name: devcontainer-cpolar-demo, build: { dockerfile: Dockerfile }, workspaceFolder: /workspace, customizations: { vscode: { extensions: [ dbaeumer.vscode-eslint ] } }, forwardPorts: [3000], portsAttributes: { 3000: { label: Demo Web Service, onAutoForward: notify } }, postCreateCommand: npm install, remoteUser: node }这份配置做了几件事使用 Microsoft 官方 Dev Container Node.js 镜像把工作目录设为/workspace首次创建容器后自动执行npm install声明 3000 端口需要转发给 3000 端口加上可读标签VS Code 端口面板里更容易识别。postCreateCommand可以放依赖安装、工具初始化这类开发环境准备动作。业务服务本身不要放在这里自动启动手动执行npm run dev更方便观察日志和排错。六、用 VS Code 打开 Dev Container在项目目录里启动 VS Codecode .按Command Shift P或Ctrl Shift P打开命令面板执行Dev Containers: Reopen in ContainerVS Code 会根据.devcontainer/devcontainer.json构建镜像、创建容器、安装依赖。第一次构建需要下载基础镜像耗时取决于网络和机器性能。进入容器后VS Code 左下角会显示类似Dev Container: devcontainer-cpolar-demo打开 VS Code 终端确认当前环境已经在容器里node -v pwd whoami正常输出类似v22.x.x /workspace node这说明同事在自己的电脑上打开同一个仓库时也会进入一致的 Node 版本、工作目录和用户环境。七、在容器内运行示例服务在 VS Code 容器终端中执行npm run dev看到类似日志即可Server listening at http://0.0.0.0:3000然后在宿主机浏览器访问http://localhost:3000 http://localhost:3000/preview http://localhost:3000/health也可以在本机终端验证接口curl http://localhost:3000/health正常返回{ok:true,uptime:12.345}如果浏览器能打开/preview说明容器内服务和宿主机端口映射已经跑通。八、端口映射怎么理解Dev Containers 里常见的端口问题本质上是调用路径没理清。这次示例里Node 服务在容器内监听0.0.0.0:3000VS Code 根据forwardPorts把容器端口转发到宿主机localhost:3000cpolar 再把宿主机上的 3000 端口映射成公网 HTTPS 地址https://xxxx.cpolar.top所以请求链路是远程同事浏览器 - cpolar HTTPS 地址 - 你的宿主机 localhost:3000 - VS Code / Docker 端口转发 - Dev Container 内 Node.js 服务 0.0.0.0:3000如果某一步失败就按这个链路从内到外检查。先在容器终端看服务日志再在宿主机浏览器打开localhost:3000最后再看 cpolar 公网地址。九、用 cpolar 生成临时 HTTPS 远程验收地址确认宿主机可以访问http://localhost:3000/preview后在宿主机终端执行cpolar http 3000cpolar 启动后终端会显示公网访问地址通常包含https://和http://两种。验收时优先复制 HTTPS 地址例如https://demo-xxxx.cpolar.top把下面几个地址发给同事即可预览页https://demo-xxxx.cpolar.top/preview 健康检查https://demo-xxxx.cpolar.top/health 接口根路径https://demo-xxxx.cpolar.top/同事打开/preview能看到页面打开/health能看到 JSON就说明容器服务、宿主机端口、cpolar 公网入口三段链路都正常。如果你希望把隧道写成固定配置也可以编辑 cpolar 配置文件。不同系统的配置文件路径会有差异先用下面命令查看本机配置位置cpolar config增加一个名为devcontainer-demo的隧道配置tunnels: devcontainer-demo: proto: http addr: 3000然后启动指定隧道cpolar start devcontainer-demo临时验收用cpolar http 3000更直接经常复用同一个项目时再写配置文件更省事。十、给同事的验收清单远程同事不需要关心 Dev Container 细节只需要按验收目标检查功能。可以把这份清单贴到群里验收地址https://demo-xxxx.cpolar.top/preview 验收范围只看本次 Demo 页面和 /health 接口 请确认 1. 页面是否能正常打开 2. 标题、说明文案、接口状态是否符合预期 3. 刷新页面后内容是否正常返回 4. 移动端浏览器打开是否变形 5. 访问 /health 是否返回 ok: true。 验收结束后我会关闭公网入口。如果是接口类服务可以再补一条 curl 示例curl https://demo-xxxx.cpolar.top/health如果是前端页面、Storybook、Swagger UI则把具体页面路径写清楚避免同事打开根路径后不知道看哪里。十一、安全边界只开放验收需要的东西Dev Container 是开发环境不是默认安全加固过的线上环境。用 cpolar 做公网预览时重点是控制暴露范围和暴露时间。可以遵守这些边界只开放 Web 预览端口例如 3000、5173、6006、8080不开放 Docker API、SSH、数据库、Redis、管理后台等高风险端口示例服务连接测试库或假数据不连接生产数据库不在页面上展示真实用户手机号、邮箱、订单、token、cookie隧道地址只发给参与验收的人不公开贴到论坛、文章、社交平台验收窗口结束后立即关闭 cpolar 进程服务日志里如果出现异常访问先停隧道再排查需要账号的 Demo 使用临时账号验收结束后删除或改密。对于有写操作的接口可以临时加一个简单保护。比如要求请求带上验收 tokenapp.addHook(preHandler, async (request, reply) { if (request.url /health || request.url /preview) { return; } const expected process.env.REVIEW_TOKEN; if (!expected) { return; } const actual request.headers[x-review-token]; if (actual ! expected) { return reply.code(401).send({ error: invalid review token }); } });启动服务时设置 tokenREVIEW_TOKENdev-review-20260708 npm run dev远程调用接口时带上请求头curl -H x-review-token: dev-review-20260708 https://demo-xxxx.cpolar.top/health页面预览可以不加 token写接口、调试接口和内部数据接口需要加限制。更高安全要求的项目应使用正式网关、认证系统、访问控制和审计日志。十二、常见问题和排错1. VS Code 没有 Reopen in Container先确认安装了 Dev Containers 插件。插件安装后重新打开 VS Code再检查命令面板。也可以确认项目根目录下存在.devcontainer/devcontainer.json文件名和目录名要完全一致不能写成.devcontainers或dev-container.json。2. 容器构建失败先看 VS Code Dev Containers 的构建日志。常见原因有基础镜像下载失败、Docker Desktop 没启动、公司代理没有配置到 Docker。可以先单独拉取镜像验证网络docker pull mcr.microsoft.com/devcontainers/javascript-node:1-22-bookwormDocker Desktop 正常后再执行Dev Containers: Rebuild Container。3.npm install失败进入容器终端后手动执行npm install --verbose如果是网络问题可以配置 npm 镜像源npm config set registry https://registry.npmmirror.com npm install团队项目里可以把可用 registry 写进项目文档或 Dev Container 初始化脚本避免每个人重复排查。4. 宿主机打不开localhost:3000先在容器终端确认服务在监听npm run dev再确认服务监听的是0.0.0.0不是127.0.0.1。这里示例里是await app.listen({ host: 0.0.0.0, port: 3000 });然后打开 VS Code 的Ports面板查看 3000 端口是否已经转发。没有转发时可以手动添加 3000或者重新加载窗口。5. cpolar 地址打不开按顺序检查curl http://localhost:3000/health cpolar http 3000本机localhost:3000都打不开时先修服务和端口转发本机能打开但 cpolar 地址打不开时再看 cpolar 客户端日志、账号登录状态和隧道状态。也要确认复制给同事的是完整 HTTPS 地址包含路径时不要漏掉/preview。6. 页面能打开但接口请求失败前端页面通过 cpolar 打开后如果页面内部还写死请求http://localhost:3000/api远程同事浏览器里的localhost指向的是同事自己的电脑不是你的机器。解决方式是使用相对路径fetch(/health)不要在前端代码里写死fetch(http://localhost:3000/health)这样页面从https://demo-xxxx.cpolar.top/preview打开时请求会自动发到同一个 cpolar 域名。7. 热更新不生效如果你换成 Vite、Next.js、Storybook 等带热更新的服务需要确认热更新端口也被正确转发。有些工具除了 Web 端口还会用 WebSocket 连接。以 Vite 为例开发服务需要监听0.0.0.0npm create vitelatest vite-demo -- --template react cd vite-demo npm install npm run dev -- --host 0.0.0.0同时在.devcontainer/devcontainer.json里转发 Vite 默认端口{ forwardPorts: [5173], portsAttributes: { 5173: { label: Vite Dev Server, onAutoForward: notify } } }8. 容器里能访问依赖服务远程页面访问不到如果服务依赖数据库、Redis、Mock API要确认依赖服务也在容器网络或宿主机网络里可达。远程同事只能访问你通过 cpolar 暴露出来的 Web 入口不能直接访问容器内部网络。验收页面应该由你的后端服务统一返回结果避免让浏览器直接连接内网数据库、内网接口或容器 DNS 名称。9. 端口被占用宿主机 3000 端口被占用时可以换一个端口。比如把服务端口改成 3100PORT3100 npm run dev同时修改.devcontainer/devcontainer.json{ forwardPorts: [3100], portsAttributes: { 3100: { label: Demo Web Service, onAutoForward: notify } } }启动 cpolar 时也跟着改cpolar http 3100端口号要三处一致服务监听端口、VS Code 转发端口、cpolar 映射端口。十三、把模板扩展到真实项目上面的示例是 Node.js但思路可以直接迁移到其他开发栈。Python FastAPI 项目可以在.devcontainer里使用 Python 镜像{ name: fastapi-devcontainer-demo, image: mcr.microsoft.com/devcontainers/python:1-3.12-bookworm, workspaceFolder: /workspace, forwardPorts: [8000], portsAttributes: { 8000: { label: FastAPI, onAutoForward: notify } }, postCreateCommand: pip install -r requirements.txt, remoteUser: vscode }启动服务uvicorn main:app --host 0.0.0.0 --port 8000 --reload cpolar http 8000Storybook 项目可以转发 6006{ forwardPorts: [6006], portsAttributes: { 6006: { label: Storybook, onAutoForward: notify } } }启动npm run storybook -- --host 0.0.0.0 cpolar http 6006Swagger UI、Redoc、Mock Server、内部运营页面 Demo 都可以按同样方式处理。关键不是工具名而是把“环境复现”和“远程验收”拆成两步Dev Containers 解决前者cpolar 解决后者。十四、团队落地方式如果团队准备把这套方式长期用于开发协作可以把下面几项固化到仓库里提交.devcontainer/devcontainer.json和必要的 Dockerfile在 README 里写清楚本地启动命令和验收端口给每个预览服务设置固定端口例如前端 5173、后端 3000、文档 6006用.env.example提供测试环境变量模板不提交真实密钥对外验收时只使用测试数据在 PR 描述里附上临时预览地址和关闭时间验收完成后关闭 cpolar避免后续提交继续暴露在同一个入口。README 里可以放一段这样的说明## Local Dev Container Preview 1. Install Docker Desktop and VS Code Dev Containers extension. 2. Open this repository in VS Code. 3. Run Dev Containers: Reopen in Container. 4. Start the service inside the container: npm run dev. 5. Open http://localhost:3000/preview locally. 6. For remote review, run cpolar http 3000 on the host machine and share the HTTPS URL. 7. Stop cpolar after review.这段说明对新同事很有帮助。对方不需要从聊天记录里翻命令直接按仓库文档执行即可。十五、验收结束后关闭公网入口远程验收完成后按这个顺序收尾通知同事验收地址即将关闭在运行 cpolar 的终端按Ctrl C停止隧道刷新 cpolar 公网地址确认已经无法访问在 VS Code 终端按Ctrl C停止开发服务如果用了临时账号、临时 token验收后删除或更换检查日志里是否有异常路径、异常 IP 或高频请求。如果你用的是 cpolar 配置隧道也可以用cpolar stop devcontainer-demo关闭公网入口是这套流程里很重要的一步。开发环境的价值在于快速复现和快速验收不应该因为图省事把本地开发服务长期暴露在外网。十六、小结Dev Containers 和 cpolar 解决的是两个不同但连续的问题。Dev Containers 让同事拿到同一套开发环境Node 版本一致、系统依赖一致、启动命令一致、端口配置一致。cpolar 让已经跑通的本地服务有一个临时 HTTPS 入口方便远程同事不用拉环境也能验收页面和接口。这套组合可用于开发阶段、联调阶段和小范围验收阶段。真正上线时还是要走正式部署、正式域名、正式认证和正式监控。每个需要多人协作的项目都可以准备一份最小.devcontainer配置再给预览服务留一个清晰端口。这样下一次同事说“我这边跑不起来”或者“能不能先给我看一眼页面”时你不需要重新解释环境只需要打开容器、启动服务、临时开一个 cpolar HTTPS 地址验收完再关掉入口。