Why Vitpress + CNB Makes Blog Deployment a Breeze
This article walks through the author’s journey of building a lightweight blog with Vitpress, leveraging Cloud Native Build (CNB), EdgeOne CDN, and Obsidian plugins for image handling, providing step‑by‑step configuration and deployment scripts for a smooth, automated publishing workflow.
Friends who follow the author’s "Operations Development Stories" know that he enjoys writing and often publishes multi‑chapter posts on his public account, and he is also interested in blogging.
2018: First blog built with WordPress on domain coolops.cn.
2020: Started using Yuque knowledge base at https://yuque.com/coolops (now discontinued).
2022: Registered domain jokerbai.com and switched to Hugo.
2023: Switched to Halo for its built‑in admin panel.
2025: Migrated to Vitpress; the blog is now available at https://jokerbai.com.
The author chose Vitpress because it is lightweight and has a simple overall style, and he explains why blog developers are excited about it.
The overall setup involves the following tools:
CNB (Cloud Native Build)
EdgeOne
Obsidian
A server (or GitHub Pages, etc.)
OSS
Obsidian
Obsidianis a great tool for writing documents and blogs. Two plugins are especially useful for blogging:
Image Upload Toolkit
Local Image Plus Local Image Plus downloads web images to a local folder with minimal configuration. Image Upload Toolkit uploads images to an OSS gallery; the author configures it to use Tencent COS.
CNB
CNBis a Tencent product that provides a cloud‑native build platform, replacing the older CODING product. By adding a .cnb.yml file to the repository, the build is triggered automatically after a push.
main:
push:
- docker:
image: node:20
stages:
- node -v && npm -v && yarn -v && pnpm -v && echo $DOCKER_TAG && echo "版本号: $VERSION"The author’s blog configuration looks like this:
main:
push:
runner:
cpus: 16
services:
- docker
- git-clone-yyds
docker:
image: ccr.ccs.tencentyun.com/jokerbai/node:22.12.0-pnpm-git-alpine
volumes:
- /data/.cache:copy-on-write #声明式的构建缓存
imports:
https://cnb.cool/jokerbaix/jokberi-blog/-/blob/main/env.yaml
stages:
- name: 🖨️打印环境
script: |
node -v && npm -v && yarn -v && pnpm -v && echo $DOCKER_TAG && echo "版本号: $VERSION"
- name: 📦️安装依赖
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
script: |
pnpm install
- name: DOCKERLOGIN
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
script: |
echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin ccr.ccs.tencentyun.com
- name: 获取DOCKERIMAGE
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
script: |
echo -n "ccr.ccs.tencentyun.com/jokerbai/joker-blog:${VERSION}"
exports:
info: IMAGE_TAG
- name: ⚗️编译项目
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
script: |
pnpm docs:build # VitePress 专用命令
- name: BUILDDOCKERIMAGE
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
script: |
docker build -t ${IMAGE_TAG} .
- name: PUSHDOCKERIMAGE
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
script: |
docker push ${IMAGE_TAG}
- name: 更新博客
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
image: tencentcom/ssh
imports: https://cnb.cool/jokerbaix/jokberi-blog/-/blob/main/env.yaml
settings:
host: ${ECS_IP}
username: ${SSH_USER}
password: ${SSH_PASS}
port: 22
script: |
cd /opt/1panel/docker/compose/joker-blog/
echo "当前目录内容:"
ls -l
echo "更新 docker-compose.yaml 中的镜像版本为: ${IMAGE_TAG}"
sudo sed -i "s|image: ccr.ccs.tencentyun.com/jokerbai/joker-blog:.*|image: ${IMAGE_TAG}|g" docker-compose.yml
echo "检查更新后的配置:"
cat docker-compose.yml
echo "重启服务"
sudo docker-compose down
sudo docker-compose up -d
echo "检查服务状态:"
sudo docker-compose ps
- name: 🔔发布通知
image: tencentcom/wecom-message
if: |
[ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ]
settings:
robot: ${WECOM_BOT}
msgType: markdown
content: |
> **🎉 乔克视界 又一次发布啦!**
> **版本号:** ${VERSION}
> **构建时间:** $CUSTOM_ENV_DATE_INFO
> **提交信息:** $CNB_COMMIT_MESSAGE_TITLE
> **仓库地址:** [$CNB_REPO_URL_HTTPS]($CNB_REPO_URL_HTTPS)
> **镜像地址:** ${IMAGE_TAG}Throughout the pipeline, a conditional check [ "$CNB_COMMIT_MESSAGE_TITLE" = "BUILD" ] ensures that the build steps only run when the git commit message is "BUILD".
EdgeOne
EdgeOneis the component that makes blog developers excited; even the personal version is sufficient. It allows domain configuration, free SSL certificates with automatic renewal, and can link directly to a Page for faster access, offering a performance boost compared to using GitHub Pages.
In summary, after writing a post, a simple git push updates the blog, making the workflow effortless.
Conclusion
After work, the author likes to jot down how he writes blogs. Since entering the operations field, he constantly absorbs knowledge online; documenting it in a knowledge base, blog, or public account helps retain and apply it to his career development.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
