比GitHub更酷更好玩:腾讯Coding后继者CNB
前言
最近我开源了一个 Iphoto 项目,在做docker镜像的时候十分痛苦,因为dockerhub在国内访问并不是很理想,我甚至打包镜像后 导出,上传到我自己的网盘上来给别人下载,github访问我也要在gitee上同步一份仓库代码供人fork,最近偶然接触到腾讯CNB,一开始我以为它和gitee一样 就是一个代码托管,仔细读了文档之后,才发现它就是公司内部的Coding的功能,Coding有的它都可以实现,就是没有可视化编排,需要自己编写yaml文件来实现相同的逻辑。
其提供了制品库和代码托管,对我这种情况来说,就等于一个地方可以管理共享我的仓库代码和我的docker镜像制品,国内轻松访问我的代码和安装我打包的镜像。于是我开始研究 把我的项目迁移到CNB的可能。研究的过程中,在代码托管、制品管理、流水线构建能力之外,我还惊奇的收获了云开发环境,于是我又把我一个平时构建需要5、6分钟的前端项目 迁移到CNB,花了一些时间构建了一个自己的开发环境镜像,然后利用云开发功能去试了试开发这个比较耗时的项目,发现只需要4核cpu即可实现4分30秒编译此项目。
4核即可实现比我自己的低功耗小主机更强的性能,根据免费的额度来计算:
1600核时/4=400
意味着我每个月可以免费使用400个小时的4核云开发环境,完全能否覆盖我这种使用强度。
接下来讲讲我怎么用CNB实现云开发以及它使用上和vscode远程开发的区别。
什么是CNB
CNB 是一个云原生构建工具,它的目标是让开发者能够更方便地构建和部署云原生应用。但事实上它的能力还包括代码托管、制品管理、云构建、云开发等能力。
其支持通过yml编写编排逻辑,结合代码仓库制品,非常灵活,通俗的讲,你可以把CNB当成你拥有了:
- 免费的代码托管,每月免费100G
- 免费的构建算力,每月免费160核时
- 免费的开发机器,每月免费1600核时
因为构建流水每一个job都支持独立的docker镜像,所以相当于每个任务里面的逻辑都高度自定义,你想怎么构建就怎么构建,你想怎么部署就怎么部署,你可以把构建的制品 部署到任何地方去(阿里云、腾讯云、你的私有云、你的服务器等)。
不要小看这个1600核时,就拿前端来说,4核的性能妥妥的够用了,我测试了n100机器编译一个项目耗时6分多,用4核编译耗时4分30秒,用64核编译也是4分多,对于前端开发 来说,核心不需要很多,单核性能更重要,这个机器时9k65cpu,可用。对于密集运算的项目,1600核时可能有些不够,看你使用频率了。
云开发
因为我还没有使用云构建来部署制品,所以今天主要是用来云开发环境,所以讲讲云开发怎么玩。
定制化开发环境镜像
仓库结构
仓库只有3个文件:
- Dockerfile:构建镜像的dockerfile
- cnb.yml:构建镜像的编排文件
- sharefile.sh:我的脚本,平时开发环境用来把某个文件上传到转存服务器,方便分享用的
Dockerfile
# 基于cnb默认的开发镜像
FROM cnbcool/default-dev-env:latest
# 设置环境变量
ENV NODE_VERSION=18.20.8
ENV NVM_DIR=/root/.nvm
ENV PNPM_HOME=/root/.pnpm
ENV PATH=/root/.yarn/bin:${PNPM_HOME}:/root/.nvm/versions/node/v${NODE_VERSION}/bin:$PATH
# 安装 code-server 及其扩展
RUN curl -fsSL https://code-server.dev/install.sh | sh && \
code-server --install-extension naumovs.color-highlight \
code-server --install-extension pranaygp.vscode-css-peek \
code-server --install-extension dbaeumer.vscode-eslint \
code-server --install-extension eamodio.gitlens \
code-server --install-extension ionutvmi.path-autocomplete \
code-server --install-extension christian-kohler.path-intellisense \
code-server --install-extension esbenp.prettier-vscode \
code-server --install-extension rvest.vs-code-prettier-eslint \
code-server --install-extension MarsCode.marscode-extension \
code-server --install-extension Vue.volar \
code-server --install-extension yzhang.markdown-all-in-one \
code-server --install-extension shd101wyy.markdown-preview-enhanced \
code-server --install-extension unifiedjs.vscode-mdx && \
echo done
# 安装 zsh 并清理缓存
RUN echo "deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib" > /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/debian/ bullseye main non-free contrib" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian-security/ bullseye-security main" >> /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/debian-security/ bullseye-security main" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib" >> /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib" >> /etc/apt/sources.list && \
apt-get update && apt-get install -y zsh rar && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# 安装 nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
# 安装 Node.js 版本
RUN bash -c "source $NVM_DIR/nvm.sh && \
nvm install ${NODE_VERSION} && \
nvm alias default ${NODE_VERSION} && \
nvm install 16 && \
nvm install 18 && \
nvm install 20"
# 配置 npm 和 pnpm 镜像
RUN bash -c "source $NVM_DIR/nvm.sh && \
npm config set registry https://registry.npmmirror.com && \
npm install -g typescript yarn bun && \
npm install -g pnpm@7.33.6 && \
pnpm config set registry https://registry.npmmirror.com"
# 安装 Oh My Zsh
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
# 复制脚本并设置权限
COPY sharefile.sh /usr/local/bin/sharefile
RUN chmod 755 /usr/local/bin/sharefile
# 配置 nvm 到 zshrc
RUN echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc && \
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.zshrc && \
echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion' >> ~/.zshrc && \
echo 'export LC_ALL=C.UTF-8' >> ~/.zshrc && \
echo 'export LANG=C.UTF-8' >> ~/.zshrc
# 设置入口点
ENTRYPOINT ["zsh", "-c", "source $NVM_DIR/nvm.sh && exec /bin/zsh"]
# 设置默认 shell 为 zsh
RUN chsh -s $(which zsh)
# 设置语言环境
ENV LANG C.UTF-8
ENV LANGUAGE C.UTF-8
上面的 && code-server —install-extension unifiedjs.vscode-mdx \ 部分内容,后面的unifiedjs.vscode-mdx
是vscode插件id,可以在你自己的vscode
中右击插件复制id,但是需要注意有些插件在code-server上不存在,会导致构建镜像失败。
然后是.cnb.yml
文件,这个文件定义了当代码提交时自动构建docker制品,配置语法、配置项参考文档 https://docs.cnb.cool/zh/build/grammar.html
# .cnb.yml
$:
vscode:
- runner:
cpus: 64
dokcer:
image:
name: docker.cnb.cool/xxxxxx/workspace-node
services:
- vscode
- docker
main:
push:
- runner:
cpus: 64
services:
- docker
stages:
- name: docker build
script: docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest .
- name: docker push
script: docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest
这样当你推送代码时,这个镜像就会自动构建到制品库。
这个时候就可以在你要云开发的项目中使用这个镜像来开发代码了。
基于定制的环境镜像云开发
先在我们的业务项目中创建一个.cnb.yml
文件,这个文件定义我们开发的环境参数
内容如下:
# .cnb.yml
$:
vscode:
- runner:
cpus: 4
services:
- vscode
- docker
#这里是导入环境变量,对应的yml文件是我的私有仓库中的文件,导入后可以使用里面的变量
imports: https://cnb.cool/xxxx/kyes/-/blob/main/keys.yml
docker:
image:
# 我使用了我的开发环境镜像,它是一个私有仓库的制品,所以需要用户名和密码,用户名密码在cnb个人设置里面创建token
name: docker.cnb.cool/xxxx/node-dev
# 导入我的cnb用户名
dockerUser: $CNB_USER
# 导入我的cnbtoken
dockerPassword: $CNB_TOKEN
volumes:
# 把node_moduels缓存起来,这样每次进入开发环境不用重复安装依赖
- node_modules:copy-on-write
stages:
# 开发环境启动后会执行的任务
- name: install
script: npm i --force
配置好之后,我们点击这里即可启动云开发环境
启动后我们可以选择3种方式开发
- WebIDE:在浏览器中打开vscode
- Vscode:使用vscode远程开发
- Cursor:使用cursor远程开发
比如我这里为了方便演示直接使用WebIDE(实际开发使用客户端体验更好)
现在可以在本机访问 http://localhost:5173 查看效果了。
Web开发需要监听0.0.0.0,否则端口转发不能正常访问到
和远程开发有哪些不同
这个云开发和远程开发有很多不同,其中最大的差异在一,云原生=临时=无状态,因为环境的启动时基于docker镜像,因此关闭环境,你的改动就会丢失,不过cnb为我们做了一些缓存处理,你的代码改动未提交到git 也不会丢失,但是如果你添加的内容是在.gitignore里面的,还是会丢失的。如果需要缓存需要使用volumes来缓存, 参考文档
然后你一切的个性化的定制,都需要你在构建开发环境镜像时,写到镜像中,比如你要特定的pnpm版本,需要特定的软件、等,都需要在环境镜像中写入。
我的做法就是构建环境镜像时尽可能和我自己的远程开发机保持一致,比如我喜欢使用ohmyzsh,我就把我的zsh配置文件也写入镜像中, 这样我所有的项目都可以使用这个环境镜像来开发,能保持和我之前的开发习惯一致。
另外因为是docker,所以像vscode的扩展,需要也在镜像构建时就安装好,不能在vscode远程开发的时候安装,重启就丢了,还有vscdoe的配置文件,你也只能创建工作区的setting,不能 创建“远程”setting,会丢失的。
最后
云开发、云构建是基于组织的,免费额度也是基于组织,因此如果你几个人一起使用一个组织是可以共享额度的,便于协作。
云开发和远程开发机有一些差异,主要是docker的特点带来的,CNB是Coding的后继者,是腾讯未来主推的,Coding因为架构的原因,只会维护,未来是CNB的天下, 其灵活的构建方法注定了它的可玩性非常非常高,只要你熟悉docker,你可以实现任何你的构建、部署逻辑。
不说了,我要去把我的项目迁移到CNB去了。