个人开发习惯是一个修改要差不多成型了才会 pull,我猜想任何人都不可能随时和代码仓库保持同步。在最近一批尚在本地的 commit 随着 MacBook 脆弱的平板一同死无全尸以后,痛定思痛,我决定把开发放在远程。这带来的好处不仅是无需在各个客户端配置环境,而且也有助于解决本地固有的一些困难,比如我不想装 Web Server 和本地数据库。
通过部署 VS Code Server 可以很方便地实现这一点,微软的文档也写得比较完整,但里面有些容易引起混淆的提法,检索相关讨论都比较混乱,需要一些厘清。
什么是 VS Code Server
是的,竟然得从这里讲起。
Code Server 与 VS Code Server
很多人混淆了 Code Server 与本文讨论的 Visual Studio Code Server。前者是 Coder 公司出品的 Web IDE 产品的一部分,它允许你部署一套 VS Code 给自己通过 Web 来使用。而后者是微软官方提供的 VS Code 后端服务,你可以将它部署在服务器上然后通过既有客户端连接使用。这里说的既有客户端包括微软提供的 Web UI(https://vscode.dev)。
大体上他们能做到一样的事,恰好微软自己也将 VS Code 简称为 Code,于是他们也有高度雷同的命名,引起了一些混乱。
实际上,VS Code 现在就是 CLI 加上一套 UI,而 UI 显然是基于 Web 技术(电脑里又多了一个 Chromium),因此 Coder 公司和微软自己能够实现这样的产品/服务并且与本地版高度一致,是可以想象的。两者对解决方案的规划稍有不同,Coder 的 Code Server 提供的是前后端一整套产品,而 VS Code Server 描述的只有 Server 端,你仍然需要通过本地的 VS Code 或微软提供的网页版连接。
这里我们讨论的是微软官方出品的 VS Code Server,它没有第三方的东西,并且扩展市场支持官方扩展。(想不到卡脖子在这里吧。)
VS Code Server 与 VS Code CLI
官方文档里讲了个 What's this 就快进到使用 Code CLI 进行 tunneling 了,而 Code CLI 和 Remote - Tunnels 看上去是另外两个东西,让人摸不着头脑。这里要谢谢微软命名部,其实他想表达的只是:
- VS Code Server 是 VS Code CLI 可以提供的一个服务。
- 我们通过 CLI 的 tunnel 功能进行远程连接去实现它。
所以你不需要额外的任何东西,微软并没有单独发布一个产品,有 VS Code CLI 就行。
VS Code Server 与 Remote SSH、Tunnels、Dev Container、WSL
你可能在了解的过程中频繁地看到上面这些东西,它们是 VS Code 远程开发大礼包(Remote Development extension pack)的全家福。我认为搞出这么多独立的名称实在不是一个好主意,它可能会让你很困惑,为什么 VS Code Server 不在其中。它们与 VS Code Server 的关系是这样的:
- Remote - SSH:给 VS Code 提供了 SSH 集成,包括管理远程主机、登录凭据和文件浏览等功能,它与 VS Code Server 完全无关,存在于远程大礼包里只是因为——你就说是不是远程吧。
- Remote - Dev Containers:你可以连接到 docker 容器内部进行开发。这里微软想表达的“远程”只是在强调它不是你的宿主机,你是连接到容器里,哪怕这个容器一般就在本地。微软自己也觉得太扯淡了,现已改名为 Dev Containers,去掉了 Remote。
- Remote - WSL:你可以连接到 Windows 的 Linux 子系统(Windows Subsystem for Linux)里进行开发。这里微软想表达的“远程”只是在强调它不是你的宿主机,你是连接到子系统里,哪怕这个子系统一般就在本地。微软自己也觉得太扯淡了,现已改名为 WSL,去掉了 Remote。
- Remote - Tunnel:无需 SSH 而是通过打洞进行远程连接的方式,这个,才是用来实现 VS Code Server 的。
所以你并不需要装完 Remote 系列的满门忠烈,它们的确都可以用来进行远程连接但这个 remote 本就有微妙的差异。也不必寻找 VS Code Server 存在于何处,你只需要保证开发机上可以正常使用 VS Code 的新版 Tunnel 功能即可。
部署 VS Code Server
厘清了这一锅粥以后,我们终于可以开始了。
部署方式的探讨
本段是为了回应一种想要把事情尽可能做得“正确”的心情,来确定我们的“打开方式”是正确的,可以跳过。
如果你打算继续阅读,那么——
如前文所述,VS Code Server 是 VS Code 自带的、通过 tunnel 实现的一个功能。因此我们的选择有:
- 在开发机上安装 VS Code CLI,通过 tunnel 命令启动该服务。
- 在开发机上安装完整带 UI 的桌面版 VS Code,通过 UI 使用 tunnel 启动该服务。
我想对 99% 的开发者来说,第一种方式都更适宜,因此本文只讲第一种。
VS Code 对开发机有一定要求,推荐为 4GB 2 Cores,这对于还要运行其他服务的主机而言,也许有些重了。为了更加轻便,我们不使用虚拟机,而是使用 LXC 容器。这样我们的 VS Code Server “系统”不分配固定的宿主机资源,能够轻松塞进你已经跑了八百个 BT/NAS/Docker 的 All in one 小主机里。
可不可以不去搭这个 VS Code Server,而是使用 Dev Container?
如果你的宿主机是 NAS 系统,平常就通过 docker 来运行大部分服务,也许你有这样的意图。
我并不建议。
前面讲过,Dev Container 所谓的“远程”不是你从星巴克连回家的“远程”,因此在家里跑个 VS Code 容器需要你自行实现回家的远程连接,包括能够安全而正确地映射转发所有端口,这增加了复杂度。
而如果你能够管理 lxc,只是“心理上”希望能在“系统容器”里再嵌套一个“应用容器”,看上去更加齐整,那么更是毫无必要。开发机需要运行各种全局 CLI,可以作为系统级环境来理解。并且嵌套使用相似而不同的 lxc 与 docker,会带来权限映射等各种问题,有的可能是难以解决的。在本地运行 Dev Container,更多是为了隔离工具链,当 lxc 已经实现了更高程度的隔离,再使用 docker,只多了一些持久化的烦恼。我们的开发环境并不需要是个得分心写 YAML 才能不被清空的影子系统,实在得不偿失。
综上所述,我们要做的事就是简简单单地在 Linux Server / 虚拟机 / LXC 启动 VS Code Server 服务而已。这里我们选择最清真的 LXC。
五分钟搞定部署
一旦确定了要做什么,实际上是非常简单和顺畅的。其实你可以直接从这里开始看。
新建和启动 VS Code 使用的 LXC
略。
只是提醒毕竟是做开发用,LXC 的形式已经很自动伸缩了,硬件资源不必给得太少。
虽然回头再改也行。
获取 Code CLI
curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz
tar -xf vscode_cli.tar.gz
然后 CLI 的二进制文件就在 ./code
了。
你可以根据你的习惯创建软连接或是直接把 code 文件移动到 /usr/local/bin
以便你在任何位置都能直接使用 code
命令。
这里我们使用移动的方式。
mv ./code /usr/local/bin/code
以防你的其他用户没有执行权限,给它设置一下权限:
chmod +x /usr/local/bin/code
运行一下,看见微软啰嗦的输出信息即为安装成功。
code
(可选)新建用户
开发工具不会经常修改文件系统,因此假如你正使用 root 用户,可以换成别的:
useradd vscode #vscode为你的用户名
然后使用该用户登录,如:
ssh vscode@localhost
初始化 Tunnel
运行下面的命令开始 Tunneling:
code tunnel
交互式的命令提示会指导你完成必要的设置,首先设置一个主机名(用来在 VS Code 界面区分自己连接的主机),然后访问给出的vscode.dev
地址,根据界面上的信息登录你的 VS Code (微软 /Github)账号,就能看到配置已完成。
回到开发机,交互式命令行告诉了你基本的操作方式,输入 x
可以停止当前的 tunneling,而你随时 Ctrl + C 离开不会使得 tunneling 中断。
作为服务启动
现在无法在被连接时自动拉起,确认一切正常以后我们回到 tunneling 处输入 x
退出,然后设置服务启动。
尝试运行:
code tunnel service install
你可能会遇到 dbus session 创建失败的问题,首先我们检查 dbus 是否已安装:
systemctl --user status dbus
如果没有安装,你应该根据提示安装:
apt install dbus-user-session
reboot #提示要求我们重启一下
然后启动 dbus:
systemctl --user status dbus
再次尝试安装 VS Code 的 tunnel 服务:
code tunnel service install
现在应该可以运行了。
Troubleshooting:被提示 error creating dbus session: I/O error: No such file or directory (os error 2) 或 Failed to connect to bus: No medium found
查找资料的时候看见一些使用 LXC 来部署服务的人在询问这个问题,很奇怪似乎很少有人提供了正确的解决。
这个问题与 VS Code 一点关系也没有。它是因为,当你使用 LXC,你很可能是以某种形式直接从宿主机访问容器。例如,你从 Proxmox 宿主机连接 LXC 容器的 Shell,或者,你使用 su - vscode
这样的方式切换用户。
通过这种方式切换用户身份,此时容器内没有 dbus 所需要的上下文。如果你尝试访问 /run/user/
,你会发现根本没有这个目录。
解决方法非常简单,使用 SSH 的方式登录该用户即可:
ssh vscode@localhost
然后再次尝试安装 VS Code 的 tunnel 服务,你应该可以看到成功了。
code tunnel service install
In English (hope it's helpful to u :)
While searching, I noticed some people using LXC to deploy the service asking this question, and it's surprising how few seem to provide a correct solution.
This issue has nothing to do with VS Code. It arises because when using LXC, you're likely accessing the container directly from the host in some way. For example, you might connect to the LXC container's shell from the Proxmox host, or switch users with a command like su - vscode
.
Switching user identities in this way means there's no necessary dbus context within the container. If you try to access /run/user/
, you'll find the directory doesn't even exist.
The solution is quite simple: just log in using SSH:
ssh vscode@localhost
Then, try installing the VS Code tunnel service again, and you should see it succeed:
code tunnel service install
效果演示
现在你可以随时随地通过浏览器访问自己的开发机,开发体验与本地几乎一致。Shell 输入略有延迟,但也不超过普通的 Web Shell 水平。
如果你做 Web 开发在开发机本地映射出了端口,VS Code 会自动发现并为你提供一个 TLS、带微软账号鉴权的外部访问地址。
如果需要安装什么,打开 VS Code 的终端,你可以像是在容器本地使用终端一样使用它。
在没有连接时,整个 LXC 容器内存占用在 200MB 以内,CPU 占用几乎可以忽略不计。