CNB × Lighthouse | 解锁构建部署新姿势

  • ~11.59K 字
  • 次阅读
  • 条评论
  1. 1. 前言
  2. 2. 以 Hexo 为例的静态站点构建与部署
    1. 2.1. 从 CNB 同步到 GitHub
    2. 2.2. 自动构建并打包产物
    3. 2.3. 部署到服务器
  3. 3. 以 Go 为例的 Docker 容器化部署
    1. 3.1. 自动构建
    2. 3.2. 部署到服务器
  4. 4. 结语

前言

以下是官方对 CNB 和 Lighthouse 的简单介绍:

云原生构建(Cloud Native Build,CNB)提供代码托管、云原生构建、云原生开发、AI 代码助手和制品库等功能。基于 Docker 生态,对环境、缓存、插件进行抽象,通过声明式的语法,帮助开发者以更酷的方式构建软件。

轻量应用服务器(Tencent Cloud Lighthouse)是新一代开箱即用、面向轻量应用场景的云服务器产品,助力中小企业和开发者便捷高效的在云端构建网站、Web应用、小程序/小游戏、AI Agent、游戏服、电商应用、云盘和开发测试环境,相比普通云服务器更加简单易用且更贴近应用,以高性价比套餐形式整体售卖云资源,将热门软件打包实现一键构建应用,提供极简上云体验。


本文将结合 CNB 和 Lighthouse 的功能,以 Hexo 和 Go 为例,从前端的静态站点部署和后端的 Docker 容器化部署两方面,讲讲 CNB 和 Lighthouse 在构建和部署上的用法。

坐稳扶好,我们发车咯~

以 Hexo 为例的静态站点构建与部署

这是我的博客,由 Hexo 驱动,目前在 CNB 和 GitHub 均有仓库且都为私有仓库:

CNB的私有仓库

GitHub的私有仓库

因此我的需求很简单:

  • 由于 CNB 在大陆的拉取和推送体验优于 GitHub,每次更新博客后会推送到 CNB,希望能自动同步到 GitHub;
  • 推送后自动运行 Hexo 生成器进行构建并打包产物;
  • 将构建产物安全部署到服务器。

下面我将通过 CNB 提供的 git-syncattachmentstcloud-cmd 三个官方插件实现以上需求。

从 CNB 同步到 GitHub

在根目录创建 .cnb.yml,该文件用于配置 CNB 流水线。

根据语法手册,我希望在所有分支的推送事件触发流水线,应配置如下规则:

1
2
3
"**":
push:
- stages:

"**" 用于匹配任意分支push 表示推送事件,即匹配任意分支的推送事件;

stages 用于定义串行的阶段任务,也是我们接下来要配置的部分。

根据插件 git-sync 的说明,我们来填写同步任务所需的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
"**":
push:
- stages:
- name: Sync to GitHub
image: tencentcom/git-sync
imports:
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/github.yml
settings:
target_url: https://github.com/zhxycn/blog.git
auth_type: https
username: ${username}
password: ${token}
force: true

这里出现了 imports,我们要用它来导入密钥仓库里的配置文件,导入后,可以在该阶段通过环境变量来读取对应值。关于密钥仓库的说明,可以在这里找到。


在这之前,我们需要先前往 GitHub 生成一个密钥:

  • 在浏览器打开 https://github.com/settings/tokens 创建一个新的访问密钥:

    创建访问密钥

  • 为密钥配置 repoworkflow 权限:

    配置密钥权限

  • 得到了 Token!我们记下来备用:

    访问密钥

在密钥仓库创建一个文件,命名为 github.yml,内容如下:

1
2
username: 你的 GitHub 用户名
token: 刚刚从 GitHub 得到的 Token

然后复制地址栏的链接到 imports 下,就完成了配置导入。


比如,我可以将现在这篇写了一半的文章推送到 CNB 的 new 分支,测试是否能正常同步:

1
2
3
4
git checkout new
git add .
git commit -m ":pencil: p218: CNB × Lighthouse | 解锁构建部署新姿势"
git push origin new

从云原生构建的运行日志中可以看到,流水线成功运行:

云原生构建的运行日志

再看看 GitHub 仓库,完美~

GitHub 仓库

自动构建并打包产物

我希望仅在 main 分支推送时触发自动构建,同时由于 Hexo 依赖 Node.js,我们指定 node:24 镜像作为构建时使用的基础环境,可以这样配置:

1
2
3
4
5
6
main:
push:
- docker:
image: node:24
volumes:
- /usr/local/share/.cache/yarn:cow

这里的 volumes 用来定义数据卷,我们将数据卷以 cow (copy-on-write) 类型挂载到 /usr/local/share/.cache/yarn,该目录用来存放 Yarn 的缓存,加快构建流程。

完成了基础环境的定义,接下来就该定义构建流程了。配置过程和在终端运行一样,我们只需要按步来定义需要执行的命令就可以了。

1
2
3
4
5
stages:
- name: Install dependencies
script: yarn install
- name: Build
script: yarn build

Hexo 生成器会将构建后的内容存放到 /public 目录,我们将目录下的文件打个包,暂且命名为 dist.tar.gz 吧~

1
2
- name: Pack files
script: tar -C public -cf - . | gzip -9 > dist.tar.gz

然后使用 attachments 插件把它上传到云原生构建的附件里:

1
2
3
4
5
- name: Upload to attachments
image: cnbcool/attachments:latest
settings:
attachments:
- dist.tar.gz

那么完整的配置应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"**":
push:
- stages:
- name: Sync to GitHub
image: tencentcom/git-sync
imports:
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/github.yml
settings:
target_url: https://github.com/zhxycn/blog.git
auth_type: https
username: ${username}
password: ${token}
force: true
main:
push:
- docker:
image: node:24
volumes:
- /usr/local/share/.cache/yarn:cow
stages:
- name: Install dependencies
script: yarn install
- name: Build
script: yarn build
- name: Pack files
script: tar -C public -cf - . | gzip -9 > dist.tar.gz
- name: Upload to attachments
image: cnbcool/attachments:latest
settings:
attachments:
- dist.tar.gz

运行一下试试效果:

云原生构建的附件

部署到服务器

对于一个静态资源来说,部署方式多种多样,可以使用 scprsync,官方也提供了相应的插件。但对于博主这样禁用了公网 SSH 和 22 端口的服务器来说,显得有点麻烦。

不过,既然 CNB 和腾讯云打通了生态,那就不得不拿出自动化助手 TATtcloud-cmd 插件了~

Lighthouse 服务器自带 TAT 客户端,但在开始之前,我们还是要检查一下 TAT 是否正常安装并运行。

在轻量应用服务器详情页的最底部,我们能看到 TAT 的状态:

TAT 状态

随后再前往 https://console.cloud.tencent.com/cam 快速新建一个子用户:

创建子用户

注意红色方框内的内容,我们需要设置访问方式为编程访问,仅授予 QcloudTATFullAccess 权限取消勾选重置密码,关闭操作保护并创建。

这样,我们就拿到了能调用 TAT 的密钥:

访问密钥

和上文一样,在密钥仓库创建一个 tcloud.yml 文件,将刚刚拿到的密钥填入:

1
2
secret_id: 
secret_key:

先贴出我的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- name: Deploy
image: tencentcom/tcloud-cmd
imports:
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/tcloud.yml
settings:
secret_id: ${secret_id}
secret_key: ${secret_key}
region: ap-shanghai
instance_ids: lhins-a1b2c3d4
script: |
curl -L --fail \
-H "Authorization: Bearer ${CNB_TOKEN}" \
-H "Accept: application/vnd.cnb.api+json" \
-o ~/dist.tar.gz \
"${CNB_API_ENDPOINT}/${CNB_REPO_SLUG}/-/commit-assets/download/${CNB_COMMIT}/dist.tar.gz"
mkdir -p ~/dist
tar -C ~/dist -xzf ~/dist.tar.gz
rsync -avz --delete ~/dist/ /www/wwwroot/blog/
rm -rf ~/dist ~/dist.tar.gz

除了 imports,这里还有几个参数需要注意一下,要根据情况来修改:

参数 说明
region 服务器所在地域,可以从这里查询,一般为 ap-<地区名称>
instance_ids 服务器实例 ID,可以在服务器详情页找到,支持以 , 分隔的多个实例
script 要在服务器上执行的命令

由于我的仓库为私有仓库,下载构建阶段生成的附件需要鉴权,因此需要使用 curl 命令携带 Authorization 头进行下载,当然公开仓库不需要这一步。

通过查询 CNB 的默认环境变量CNB_TOKEN 为用户临时令牌,会在流水线结束时销毁,可用于代码和制品的拉取、推送以及 API 调用。

云原生构建附件的目录也可以通过拼接得出:

1
${CNB_API_ENDPOINT}/${CNB_REPO_SLUG}/-/commit-assets/download/${CNB_COMMIT}/dist.tar.gz

于是很容易写出如下命令:

1
2
3
4
5
curl -L --fail \
-H "Authorization: Bearer ${CNB_TOKEN}" \
-H "Accept: application/vnd.cnb.api+json" \
-o ~/dist.tar.gz \
"${CNB_API_ENDPOINT}/${CNB_REPO_SLUG}/-/commit-assets/download/${CNB_COMMIT}/dist.tar.gz"

接下来是解压后放到对应目录,就不用多说了:

1
2
3
4
mkdir -p ~/dist
tar -C ~/dist -xzf ~/dist.tar.gz
rsync -avz --delete ~/dist/ /www/wwwroot/blog/
rm -rf ~/dist ~/dist.tar.gz

这样,我们就完成了一个静态站点从构建到部署的自动化流程,最后贴一下完整的流水线配置吧~

完整配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
main:
push:
- docker:
image: node:24
volumes:
- /usr/local/share/.cache/yarn:cow
stages:
- name: Install dependencies
script: yarn install
- name: Build
script: yarn build
- name: Pack files
script: tar -C public -cf - . | gzip -9 > dist.tar.gz
- name: Upload to attachments
image: cnbcool/attachments:latest
settings:
attachments:
- dist.tar.gz
- name: Deploy
image: tencentcom/tcloud-cmd
imports:
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/tcloud.yml
settings:
secret_id: ${secret_id}
secret_key: ${secret_key}
region: ap-shanghai
instance_ids: lhins-a1b2c3d4
script: |
curl -L --fail \
-H "Authorization: Bearer ${CNB_TOKEN}" \
-H "Accept: application/vnd.cnb.api+json" \
-o ~/dist.tar.gz \
"${CNB_API_ENDPOINT}/${CNB_REPO_SLUG}/-/commit-assets/download/${CNB_COMMIT}/dist.tar.gz"
mkdir -p ~/dist
tar -C ~/dist -xzf ~/dist.tar.gz
rsync -avz --delete ~/dist/ /www/wwwroot/blog/
rm -rf ~/dist ~/dist.tar.gz

在调用 TAT 运行后,我们还可以在命令执行记录中查看运行结果,满足了调试和审计需求:

运行结果

以 Go 为例的 Docker 容器化部署

这是一个由我和团队维护的 Go 语言项目:

项目仓库

对于这个项目,我的需求如下:

  • main 分支提交后,自动构建 dev 标记的 Docker 镜像,然后部署到测试环境;
  • 在测试完成,创建 Tag 后,自动构建 latest 标记的 Docker 镜像,然后部署到生产环境。

下面我将通过 CNB 的 Docker 制品库和 tcloud-cmd 插件实现以上需求。

自动构建

对于一个在 Docker 运行的项目,自然少不了 Dockerfile,我们应该将程序的构建过程在 Dockerfile 中完成定义:

Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FROM golang:alpine AS builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o server ./cmd

FROM alpine:latest

WORKDIR /app

COPY --from=builder /app/server .

ENV TZ="Asia/Shanghai"
ENV DATABASE=""

EXPOSE 8080

CMD ["./server"]

有了 Dockerfile,构建镜像就很简单了:

1
2
3
4
5
6
7
8
9
main:
push:
- services:
- docker
stages:
- name: docker build
script: docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:dev .
- name: docker push
script: docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:dev

这两步会生成一个与仓库同名的镜像,并推送到仓库对应的制品库中。至于生产环境,我们只需要稍微调整一下触发条件和 Docker 镜像的标签:

1
2
3
4
5
6
7
8
9
$:
tag_push:
- 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

在运行成功后,就可以在制品库中看到构建的镜像了:

制品库

部署到服务器

和上文一样,我们依然可以使用 tcloud-cmd 插件调用 TAT 在服务器中完成镜像的拉取和部署,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- name: Deploy
image: tencentcom/tcloud-cmd
imports:
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/tcloud.yml
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/project.yml
settings:
secret_id: ${secret_id}
secret_key: ${secret_key}
region: ap-shanghai
instance_ids: lhins-a1b2c3d4
script: |
sudo docker stop ${CNB_REPO_NAME_LOWERCASE} || true
sudo docker rm ${CNB_REPO_NAME_LOWERCASE} || true
sudo docker run -d --name ${CNB_REPO_NAME_LOWERCASE} \
-p 8080:8080 \
-e TZ="Asia/Shanghai" \
-e DATABASE="${DATABASE}" \
${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:dev
query_instance: true

镜像拉取可以通过腾讯云内网完成,在解决了 Docker Hub 在国内无法拉取的痛点上,又提高了部署效率。

对于不同部署环境来说,只需要调整对应的定义。若仓库为私有仓库,需要多一条登录到 CNB Docker 制品库的命令:

1
sudo docker login docker.cnb.cool -u cnb -p ${CNB_TOKEN}

除文中提到的流水线外,高阶用户还可以参考文档中的自定义部署流程来实现审批流程。同样的,也可以利用 YAML 语法特性来简化配置文件

以下是经过简化的完整配置~

完整配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
.job: &job
services:
- docker
stages:
- name: docker build
script: docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:${image_tag} .
- name: docker push
script: docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:${image_tag}
- name: Deploy
image: tencentcom/tcloud-cmd
imports:
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/tcloud.yml
- https://cnb.cool/CatNya/zhxycn/secrets/-/blob/main/project.yml
settings:
secret_id: ${secret_id}
secret_key: ${secret_key}
region: ap-shanghai
instance_ids: ${instance_ids}
script: |
sudo docker stop ${CNB_REPO_NAME_LOWERCASE} || true
sudo docker rm ${CNB_REPO_NAME_LOWERCASE} || true
sudo docker run -d --name ${CNB_REPO_NAME_LOWERCASE} \
-p 8080:8080 \
-e TZ="Asia/Shanghai" \
-e DATABASE="${DATABASE}" \
${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:${image_tag}
query_instance: true
main:
push:
- env:
instance_ids: lhins-a1b2c3d4
image_tag: dev
<<: *job
"*":
tag_push:
- env:
instance_ids: lhins-a1b2c3d4
image_tag: latest
<<: *job

结语

CNB 与腾讯云生态结合带来了高效的 CI/CD 流程。无论是静态站点的自动更新,还是容器化应用的持续交付,CNB 强大的插件生态和声明式的流水线配置,无疑能简化我们的构建与部署工作。

赞助喵
非常感谢您的喜欢!
赞助喵
分享这一刻
让朋友们也来瞅瞅!