为了能在 iPad 上使用 VSCode 完成一些简单的编程任务,打算在威联通 Qnap 的 NAS 上部署 VSCode 编辑器服务,对这个在线服务的基本要有:
- 能够直接编辑 NAS 上文件;
- 能够使用 Qnap Container Station 应用的容器实例;
- 能够进行 Python、Node.js 及 Rust 应用开发。
在网上进行检索之后发现两种部署方案:
- 使用
linuxserver/code-server
部署基于浏览器的 VScode 服务; - 使用
linuxserver/vscodium
部署基于浏览器的 VSCode 服务;
coder-server
是一个开源的项目,使用 code-server
可以在浏览器中访问 VSCode
编辑器。它提供了一个基于 Web 的集成开发环境(IDE),使开发者能够通过浏览器远程访问和使用 VSCode
的功能,而无需在本地安装 VSCode
。
code-server
的工作原理是在服务器上运行一个 VSCode
实例,然后通过 WebSocket
将 VSCode
的用户界面传输到客户端浏览器中。
vscodium
是一个开源版本的 VSCode
。与 VSCode
相比,其主要区别在于 VSCodium
不包含 Microsoft 的 Logo、构建标识和 Telemetry 数据收集相关的代码。
vscodium
和 code-server
的对比
在体验时使用的均为 LinuxServer 提供的镜像,两者之间的体验差异如下:
差异/镜像 | linuxserver/vscodium | linuxserver/code-server |
---|---|---|
基础镜像体积 | 2.41G | 570MB |
客户端 | Web 浏览器 | Web 浏览器 |
流畅程度 | 卡顿感明显 | 与桌面版无异 |
界面显示 | 默认配置锯齿明显,需要调整缩放(iPad 上看还算正常) | 正常 |
中文显示 | 需要手动安装中文字体 | 可正常显示 |
中文输入 | 无法使用快捷键切换 | 可正常切换 |
插件 | 无限制 | 无法使用桌面版应用的插件(如 Dev Containers ) |
Docker in Docker | 支持,需要手动配置 | 支持,需要手动配置 |
是否账号支持同步 | 不支持 | 不支持 |
从流畅程度上看 linuxserver/code-server
的体验时明显优于 linuxserver/vscodium
。linuxserver/vscodium
是基于 KasmVNC 将桌面端应用转换为 Web 应用,因此其基础镜像相比 code-server
会大上不少,而且在使用时需要传输的数据量也更多。linuxserver/code-server
是原生的 Web 应用,在渲染的时候不会像 linuxserver/vscodium
一样需要传输那么多的数据量,使用的流畅度基本和在本机上使用 VSCode
没有什么区别。
在显示上,linuxserver/vscodium
的分辨率如果和本机不同,则锯齿会非常明显。并且 linuxserver/vscodium
默认情况下不支持中文的显示,需要在基础镜像的基础上安装中文字体包并进行相应的调整。因为 linuxserver/code-server
是 Web 应用,所以显示效果完全取决于本机,并不需要额外的配置。
但是两者在中文输入上都有不好的地方。linuxserver/vscodium
可以使用本机的输入法,但是必须通过左侧的控制栏进行设置,在体验的时候并没有发现能够通过快捷键进行调整的方法。而 linuxserver/code-server
的问题在于 vim 插件无法在 normal mode 时自动切换到英文输入法,如果在本机上使用的话可以通过配置 im-select 解决这个问题,但是作为 Web 应用似乎没有很好的解决办法。
从对插件的支持程度上来看,linuxserver/vscodium
比 linuxserver/code-server
具备更好的普适性。由于 linuxserver/vscodium
其实就是一个桌面版的 VSCode 应用,因此只要基础镜像操作系统中安装了必备的依赖,那么基本上所有的插件都可以使用。由于 linuxserver/code-server
是 Web 应用,并非所有的插件都能够安装(比如 Dev Containers)。
两者都不能使用 VSCode 自带的同步服务,但是如果在 NAS 上使用的话,这一项功能的有无其实并不重要。
部署 code-server 服务
在对比 linuxserver/vscodium
和 linuserver/code-server
后,从个人的角度上看 linuxserver/code-server
更能满足我的需求。下面对 linuxserver/code-server
进行一些调整以使其更符合个人的使用场景。
配置 Docker in Docker
为了启用 Docker in Docker,需要在容器启动时将 Container Station 的 docker.socker
文件映射到容器内,并且在容器内安装 docker-cli
使用宿主机 docker 服务。
要注意的是,linuxserver/code-server
中使用的默认账户是 abc
,该账户无法直接使用 docker.sock
文件,而 VSCode 中的 Docker 插件要求 rootless docker,因此需要将用户 abc
添加到 root
用户组中。
调整后的 Dockerfile 如下:
# 引入基础镜像
FROM lscr.io/linuxserver/code-server:latest
# 更换 apt 源
RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && \
apt update -y && apt upgrade -y
# 安装 docker cli
RUN apt install -y ca-certificates curl gnupg && \
install -m 0755 -d /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
chmod a+r /etc/apt/keyrings/docker.gpg && \
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt update -y && \
apt install -y docker-ce-cli docker-buildx-plugin docker-compose-plugin
# 将 abc 用户添加到 root 用户组
RUN usermod -aG root abc
coder.Dockerfile
配置 Python 开发环境
基础镜像中已经安装了 Python3.10,因此不再重复安装,如果有多版本的需求,可以通过安装 Pyenv 实现。
# 安装 pip、pipx 和 poetry
RUN apt install -y python3-pip pipx && \
pipx install poetry
coder.Dokerfile
配置 Node.js 开发环境
安装 Node.js@20 以及 yarn,如果有多版本的需求,可以通过安装 nvm 实现。
# 安装 nodejs@20
ENV NODE_MAJOR=20
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list && \
apt -y update && \
apt install nodejs -y && \
npm install --global yarn
coder.Dockerfile
配置 Rust 开发环境
直接通过 rustup 配置 Rust 开发环境,在 Dockerfile 中需要添加 -y
参数以使用默认配置直接安装。
# 安装 Rust 和依赖
RUN apt install -y libssl-dev pkg-config
RUN curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh -s -- -y
使用 docker-compose 启动服务
完成镜像的配置后,在 NAS 上使用下面的指令创建镜像:
docker build . -f coder.Dockerfile -t local/coder:latest
在 docker-compose 文件中添加如下配置:
version: "3.9"
services:
code-server:
image: local/coder:latest
container_name: code-server
extra_hosts:
- "host.docker.internal:host-gateway" # 将主机地址映射到容器内
secrets:
- hashed_password # 应用密码(使用 argon2-cli 生成)
- hashed_sudo_password # 系统 sudo 密码(使用 argon2-cli 生成)
environment:
- DEFAULT_WORKSPACE=/workspace # 启动目录
- FILE__HASHED_PASSWORD=/run/secrets/hashed_password # 使用 secret 文件指定应用密码
- FILE__SUDO_PASSWORD_HASH=/run/secrets/hashed_sudo_password # 使用 secret 文件制定系统 sudo 密码
- PROXY_DOMAIN=coder.example.com # 代理域名
- PGID=100 # 用户组 id(使用 `id` 指令查看,应当和 NAS 用户一致,否则可能会出现文件权限的问题)
- PUID=1000 # 用户 id(使用 `id` 指令查看,应当和 NAS 用户一致,否则可能会出现文件权限的问题)
- TZ=Asia/Shanghai # 时区
volumes:
- /path/to/WORKSPACE:/workspace # 工作区目录
- /path/to/coder/config:/config # code-server 配置目录
- /var/run/docker.sock:/var/run/docker.sock # Docker in Docker 配置,Container Station 的 `docker.sock` 文件
ports:
- 3000:3000 # 暴露 3000、3001 用于开发调试
- 3001:3001
- 8443:8443 # code-server 服务端口
restart: unless-stopped
secrets: # 指定 password 路径
hashed_password:
file: /path/to/code-server/_secrets/hashed_password.txt
hashed_sudo_password:
file: /path/to/code-server/_secrets/hashed_sudo_password.txt
docker-compose.yaml
在 Container Station 中运行或者通过下面的指令运行:
cd /path/to/docker-compose.yaml
docker compose up -d
启动成功后在浏览器中访问 http://<nas ip address>:8443,输入设置的密码即可。
注意,如果不使用 https
访问的话某些依赖 Service Workers 的服务将无法使用(比如 Markdown 预览)。