作为一个有追求程序员,在工作之余有时也需要搞点开发,这时开发环境就成为一个有点棘手的问题。每个程序员都希望有一个长期的、稳定的开发环境,这样用起来才顺手。用工作电脑毕竟有不方便的方面,各种全家桶、监控、访问限制……总之工作和个人的事情还是应该彻底分开。如果用自己的电脑,又不可能随时携带,不方便随时随地随地编(mo)码(yu)。这时常年开机且运行了很多外部服务的NAS自然成为了一个可以考虑的选择。我平时编码使用最多的是VSCode,VSCode本身就是基于Electron实现的,理论上可以很方便地运行在浏览器里并且获得近似于原生应用的体验。这样,只要打造一个基于Web的随时可访问的个人VSCode环境,有电脑(或者Pad)有网就可以使用,即可完美解决问题。
感谢万能的开源社区,code-server项目(GitHub - coder/code-server: VS Code in the browser)已经实现了一个Web版的VSCode,支持全功能和插件,我们可以直接使用它的Docker镜像部署。
当然,下面的方法不仅适用于NAS,个人的VPS、虚拟机,只要能被公网访问到,理论上都可以用这种方法实现,大家可以参考自行折腾。
一、前提条件
NAS或其他长期运行的服务器设备。
可公网访问。
支持Docker。
(可选)有域名,域名服务商支持API访问用于HTTPS证书自动化。
二、部署和配置
1. 以Unraid为例
我NAS使用的Unraid,所以这里以Unraid为例。其他系统支持Docker的配置方法大同小异。
在Unraid的Apps页面,搜索“code-server”,这里我们用第二个linuxserver的实现,点Install。
接下来的界面里,配置相关参数,注意以下几项:
PASSWORD:在Web浏览器里访问时使用的密码,建议设置。当然你也可以使用其他方式做权限控制。
SUDO_PASSWORD:容器内工作账号使用sudo进行系统操作时的密码。
PROXY_DOMAIN:后续公网访问使用的域名。
网络类型(Network Type):一般使用默认的桥接(Bridge)即可。如果你已经配置了公网访问并且在其他的网络里,则按需调整此项,例如我这里使用了自己的bond0。
镜像地址:个人的感觉是lscr.io的镜像拉取比较慢,可以换成Docker官方地址linuxserver/code-server,当然也可以换成其他源,或者保持不动。
点Apply,拉取镜像并安装。
稍等片刻,镜像拉取完毕后,code-server的容器就启动起来了。
2. Docker配置参考
如果你使用的不是Unraid,但是支持Docker,可以参考下面的配置进行安装。下面的命令也可以直接在安装了Docker的Linux终端运行。
docker run \ --name /code-server \ -v /home/xxx/code-server:/config:rw \ -e PASSWORD=password \ -e SUDO_PASSWORD=sudo_password \ -e PROXY_DOMAIN=code-server.example.com \ -p 8443:8443 \ linuxserver/code-server
其中,几个参数需要按需配置:
/home/xxx/code-server:指定为宿主机的目录,其中保存了插件、配置及工作目录等信息,以保证容器在重启时依然保持原有数据和配置。
password:替换为Web访问使用的密码。也可以把PASSWORD环境变量去掉,没有密码。
sudo_password:替换为工作账号使用sudo的密码。
code-server.example.com:替换成你自己的公网域名(如果有),没有的话也可以把PROXY_DOMAIN环境变量去掉。
3. 本地访问Web版VSCode
接下来,就可以尝试在浏览器里访问VSCode容器了。在Unraid中切换到Docker页面,点code-server,选择“WebUI”,或者直接在浏览器里访问对应容器的8443端口,即可访问。同一浏览器第一次访问需要输入刚才设置的密码,之后,一个VSCode界面就在浏览器里出现了,用法跟桌面版VSCode几乎一样,可以按照自己的喜好进行各种配置。
4. 配置公网访问
接下来我们需要配置一下公网访问,实现通过公网域名直达Web开发环境的目标。如果你的NAS已经配置域名的话,可以直接把域名指向code-server容器的8443端口。
这里我使用swag管理公网访问。swag是一个nginx+SSL证书管理工具的封装,能够自动实现HTTPS证书的申请和续费,并且内置了很多流行Docker应用的配置,方便NAS这种一台服务器运行多个容器提供多种服务的场景。
依然以Unraid为例,在Apps页面中搜索“swag”,点Install。这里假设自己的域名托管在DNSPod上。配置项有点多,主要有:
WebUI端口:默认为443,很多运营商家庭宽带禁止了443端口访问,所以这里需要换一个端口,例如8443。
URL:自己域名的URL,假设为example.com。
VALIDATION:验证方式,这里填写dns,申请SSL证书时通过dns的TXT记录校验域名的归属。
SUBDOMAINS:子域名,这里直接用wildcard,可以支持使用swag托管*.example.com的域名服务。
DNSPLUGIN:选dnspod。
EMAIL:填写自己的邮箱,使用ZeroSSL申请SSL证书时必填。
之后点Apply。待容器启动后,我们进入到容器中,将内置的code-server配置启用:
cd /config/nginx/proxy-confs/ cp code-server.subdomain.conf.sample code-server.subdomain.conf
之后,重启一次swag,使新配置生效。
当然还有一步,需要在DNSPod(或其他DNS提供商)处将域名指向自己的公网P,这里我们将example.com和code-server.example.com均指向公网IP。还需要去路由器上设置公网端口映射到自己的NAS HTTPS端口(即上面例子中的8443)。路由器上
一切妥当后,我们使用 https://code-server.example.com:8443 ,即可实现公网访问NAS上面的VSCode开发环境。
三、使用文心快码实现AI编码能力
上面只完成了第一步。在目前这个时代,使用AI工具提升编码效率是大势所趋。本来想顺势在NAS上面折腾一个Ollama跑个本地模型,但研究了下发现这货对GPU要求比较高,基本8G显存起步,有这个卡我干嘛不拿来玩玩悟空。所以打消了这个念头,转而寻求在线服务类的编码助手。AI编码的鼻祖当然是GitHub Copilot,不过是要收费的,而且可能还要使用魔法,你懂的,遂放弃。
继续百度了一下,发现百度自己就做了一款叫文心快码的产品,是文心大模型家族的一员,看介绍功能与Copilot类似,名字也类似,英文名叫Baidu Comate。更重要的是,文心快码个人版是免费的,续写功能完全免费,部分高级功能免费版有次数限制,看起来够用了。试用了一下,体验非常不错,所以在这里强烈推荐一下。
1. 安装文心快码插件
在介绍之前还发现一个小坑,这个插件会尝试读取/var/lib/dbus/machine-id文件,估计是设备鉴权用,但是Docker容器里并没有这个文件。不过没关系,我们把宿主机的挂载过来就好了。在Unraid里面,新增一个自定义Path,不妨命名为MachineId,容器路径和主机路径都填/var/lib/dbus/machine-id,只读,之后重启一下code-server即可。如果使用Docker命令启动,需要增加以下参数:
-v /var/lib/dbus/machine-id:/var/lib/dbus/machine-id:ro
(p.s. 这个bug官方已经给反馈了,说是后续会修复)
文心快码的使用方法很简单,只要在VSCode插件中心,搜“文心快码”或者“Comate”即可找到,插件名称又叫Baidu Comate。稍等片刻,安装完毕,右下角会提示登录,点“个人登录”,绑定百度账号后,即可免费使用个人版。
2. 使用文心快码续写代码
先来试一个Hello world吧。创建hello.c,敲#include <stdio.h>,嗯?它自动帮我提示出剩下的所有代码,只要按Tab键采纳就可以了。
3. 注释生成代码
看来过于简单了,来一道hard吧,比较著名的接雨水。按照“先写注释,再写代码”的原则,我们先把题目描述写上去……发现文心快码都会抢答了,直接给我 补上了下面的代码,还给了多种解法。美中不足的是,一次续写的长度似乎有限,我需要多次按Tab键才有可能补完,有些不连贯。
4. 使用侧边栏生成代码
基于刚才的场景,我们来试试使用侧边栏生成代码。相信不少人都用过ChatGPT、文心一言之类的工具生成代码:在网页里输入问题描述,将结果再复制粘贴到IDE里。文心快码提供了侧边栏,可以直接通过chat的方式问问题、生成代码。点击左侧的C形按钮即可打开。我们把刚才完整的题目描述粘贴到对话框里,再试一次。
我的问题描述如下:
用C语言完成下面的接雨水题目,希望代码简洁、高效,并有简要的注释。 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 示例 2: 输入:height = [4,2,0,3,2,5] 输出:9
不到一分钟,文心快码就给出了问题的完整代码,并配上了解释。看起来代码非常规整,并且配上了我要求的注释。还有一个小发现,在对话框里可以直接点击“新建文件”,自动创建一个以此代码为内容的文件,大幅度简化了用户操作。
话不多说,直接把这段代码的trap函数内容粘贴到LeetCode里面,看看能不能过。闭眼提交,直接AC,执行速度大约处于中位水平,跟我提示使用代码比较简单的算法也有关。
5. 代码生成注释
使用过程中还发现,文心快码提供了函数生成注释功能,在每个函数声明上面,会有相关的功能提示,如下图。
很多时候,我们会习惯先写函数声明,确定函数名和参数,然后再写注释,函数生成注释功能大幅度简化了这个操作的成本。点一下试试。结果发现,函数生成注释并不是直接就地填写注释,而是进入了侧边栏,相当于帮我们发了一个问题。在生成的结果中,我们可以直接点击“采纳”,即可把生成的函数注释插入到函数上面。
函数生成注释本质就是代码理解的过程,这方面没有什么问题,生成的注释很准确,格式也很规范。
6. 生成单测
写单测这种比较机械的活,自然更适合交给AI去做。刚才函数的上方有“生成单测”按钮,看下效果。
与生成注释类似,它也是将需求引入了侧边栏,生成了完整的代码。点“采纳”按钮,会自动新建同名的test代码文件,并把单测代码填入。看了下对C语言自动使用了gtest框架,并且自动把上文的两个样例作为单测用例写了进去。看来它已经具备了一定的生成上下文的能力。
7. 工程级别的代码生成
如果说上面是基础功能(花拳绣腿),只能针对单个文件操作,下面我们动点真格的试试。我平时主要写Go、Java服务端代码,对前端了解不多,JS可以说是基本不会写。下面作为小白身份,试一下文心快码能不能帮我们生成一个NodeJS工程。插件里有个叫“AutoWork”的东西,看起来是干这个的,就它了。
提示词如下(此处@AutoWork):
@AutoWork 帮我生成一个使用NodeJS写的完整工程,该工程运行在服务端,并提供Web访问,功能是做一个基于Web的报名服务,访问者可以在页面输入自己的姓名、手机号码、公司名称、备注。其中姓名、手机号码、公司名称为必填字段,手机号码需要符合中国手机号的格式。所有的提交数据按行保存在本地磁盘的CSV文件中。同时,需要生成完成的Dockerfile,通过Dockerfile构建出这个工程后,可以直接运行,并通过8080端口监听。
稍等片刻,文心快码给出了工程结构、文件名和文件内容,看起来有模有样。不过美中不足的是,它似乎并没有自动帮我创建文件结构的能力,在目录结构那里点“采纳”,居然帮我把这个目录结构建了个文本文件。不过好在每个文件旁边都有“新建文件”按钮,通过这个按照它给的目录结构,生成了完整的工程目录结构。
接下来,在宿主机上执行Docker构建并运行试一下。由于VSCode跑在Docker容器内,所以默认不能再用Docker,除非配置DinD,那就是另一个事情了。这里简单起见我们去宿主机上干。执行以下命令:
docker build -t registration-service .
看起来一切正常,我们运行一下:
docker run -it -p 8080:8080 registration-service
嗯,报错了。不过看起来是个小问题,文件不存在。
我们把这个问题交给文心快码,看看它能不能处理。
没啥问题,解决了。采纳一下,替换到原来的Dockerfile,再来一次。这次看起来能运行了,访问 http://127.0.0.1:8080 ,给我们了一个非常简单的页面,必填字段功能也实现了。
不过提交时,再次遇到了报错,这次的报错信息看起来跟文件读写相关。我们再尝试让文心快码来解决一下。
它又给出了解释和完整的修改建议,看起来与CSV文件头有关。照猫画虎,我们把相关代码改到文件里,保存,再次构建,运行。这次看起来成功提交了,去容器内看下本地文件有没有保存:
# 5c0e4acd19c0为本次运行的容器名 docker exec -it 5c0e4acd19c0 bash cat /app/data/submissions.csv
可见,我们要的文件已经正常写入了,这个功能基本实现。
总的来说,文心快码已经有了简单的工程级别代码生成能力,但是易用性和完整度上还有提升空间,在这方面的能力算是刚及格吧。如果经过更加细致的产品打磨和迭代,把一些问题在交付给用户之前提前发现和解决,并且让流程体验更加连贯,这个能力还是值得期待的。
四、总结
不知不觉,已经在这个云端IDE上玩了半天了。Web上整体的体验与本地VSCode几乎无差异,可以随时随地回到自己的开发环境。基于这个环境,完全可以进一步安装自己常见的插件、工具、配置,把它打造成自用的主力开发环境。
同时,通过文心快码AI能力的加持,又实现了云端的AI辅助开发,大幅提升开发效率。这不禁让人感叹技术的发展为我们带来的便利,ssh到服务器上用vim写代码的日子,真的是一去不复返了。