外观
部署
约 1654 字大约 6 分钟
2025-08-30
官方的部署指南可参考官网上的部署章节,本文介绍笔者所用的docker
部署方案。
构建项目
使用官方脚本创建的项目,package.json
文件中会有如下脚本命令:
{
"scripts": {
"docs:build": "vuepress build docs"
}
}
在项目根目录下运行该命令执行项目构建:
pnpm
pnpm docs:build
yarn
yarn docs:build
npm
npm run docs:build
执行完成后的构建产物会存放在docs/.vuepress/dist
目录下,其结构大致如下
docs
.vuepress
dist
article
abcd1234文章哈希值
index.html
assets站点所需静态资源
xxx.js
yyy.css
zzz.ttf
...
blog
archives
index.html
categories
index.html
tags
index.html
index.html
404.html
favicon-32x32.png
index.html
plume.svg
robots.txt
sitemap.xml
sitemap.xsl
README.md
构建Docker
镜像
创建Dockerfile
文件
在项目根目录创建Dockerfile
文件,文件目录内容大致如下:
Dockerfile
# 使用nginx-alpine作为基础镜像
FROM nginx:1.28.0-alpine3.21
# 复制构建后的文档到nginx的默认目录
COPY docs/.vuepress/dist/ /usr/share/nginx/html/
# 复制自定义nginx配置
COPY nginx.conf /etc/nginx/nginx.conf
# 暴露80端口
EXPOSE 80
# 启动nginx
CMD ["nginx", "-g", "daemon off;"]
创建.dockerignore
文件
.dockerignore
文件可以在构建docker
镜像时,忽略工作目录下的某些文件,加快项目构建速度。
在项目根目录创建.dockerignore
文件,文件内容大致如下:
.dockerignore
# 依赖目录
node_modules/
.pnpm-store/
# 构建缓存
.cache/
.temp/
# Git相关
.git/
.gitignore
.gitattributes
# 开发文件
.DS_Store
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# 环境文件
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# IDE文件
.vscode/
.idea/
*.swp
*.swo
# 测试文件
coverage/
.nyc_output/
# 其他
README.md
pnpm-lock.yaml
package.json
.npmrc
# CI/CD 和部署文件
.gitlab-ci.yml
docker-compose.yaml
# VuePress 开发文件
docs/.vuepress/.temp/
docs/.vuepress/.cache/
docs/.vuepress/.DS_Store
# 开发文档源文件(构建后不需要)
docs/notes/
docs/preview/
docs/README.md
docs/.vuepress/config.ts
docs/.vuepress/client.ts
docs/.vuepress/navbar.ts
docs/.vuepress/notes.ts
docs/.vuepress/plume.config.ts
docs/.vuepress/theme/
docs/.vuepress/public/
执行构建
docker build -t [image-name]:[image-tag] # image-name和image-tag按需设置
部署Docker
容器
此处采用docker compose
部署,没有安装docker compose
的可以参考官网安装指引
在项目根目录创建docker-compose.yaml
文件,文件内容大致如下:
docker-compose.yaml
services:
knowledge-base:
image: [image-name]:[image-tag] # 使用构建时指定的名称和标签
container_name: [container_name] # 指定容器的名称
restart: always # 始终重启
ports:
- 8888:80 # 主机8888端口映射到容器的80端口,主机端口可按需调整
在项目根目录运行以下命令启动启动容器
docker-compose up -d
之后查看容器运行状态
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c2e2b2b04b7e [image-name]:[image-tag] "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 0.0.0.0:8888->80/tcp [container-name]
最后打开浏览器输入http://localhost:8888即可访问
GitLab
中使用CI/CD
自动化部署
环境依赖
- 项目存储在
Gitlab
或自建Gitlab
上 - 已通过
Docker
方式部署好Gitlab Runner
,并且在项目中有使用该Runner
的权限 - 假设部署位置与
Gitlab Runner
在同一台主机上(下方配置基于此进行了简化)
创建.gitlab-ci.yml
文件
.gitlab-ci.yml
# 定义全局变量
variables:
DOCKER_IMAGE_NAME: $CI_PROJECT_NAME # 采用项目名作为镜像名
DOCKER_IMAGE_TAG: $DOCKER_IMAGE_NAME:$CI_COMMIT_TAG # 采用镜像名+项目tag作为最终镜像版本
# 定义阶段及顺序
stages:
- build
- docker-build
- deploy
# 缓存node_modules,避免重复下载
cache:
key:
files:
- pnpm-lock.yaml # 缓存依赖pnpm-lock.yaml文件,该文件变动则缓存失效
paths:
- node_modules/
- .pnpm-store/
# 项目构建阶段
build:
stage: build
image: node:22.18.0-alpine3.21 # 使用与项目node版本一致的镜像
script:
- export
- npm install -g pnpm@10.15.0
- pnpm config set store-dir .pnpm-store
- pnpm install --frozen-lockfile
- pnpm docs:build
artifacts:
paths:
- docs/.vuepress/dist/
expire_in: 1 week
only:
- /^rc-.*/ # 仅rc-开头的tag执行
# 镜像构建阶段
docker-build:
stage: docker-build
image: docker:latest # 基于docker镜像,使用其提供的docker命令
script:
- export
- docker build -t ${DOCKER_IMAGE_TAG} . # 构建docker
dependencies:
- build
only:
- /^rc-.*/
# 部署阶段
deploy:
stage: deploy
image: docker:latest
script:
- export
- docker-compose -f docker-compose.yaml up -d # 部署docker
only:
- /^rc-.*/
when: manual # 手动执行
测试部署
将.gitlab-ci.yml
文件提交后,在Gitlab
上的项目中,以rc-x.y.z
格式创建Tag
如果运行成功,在Build -> pipelines
下可看到如下内容,前两步骤为项目构建、Docker
构建,均自动执行,最后一步为部署,我们设定为手动执行。
点击最后一步,并点击运行。

使用阿里云镜像仓库
由于本地空间有限,为了便于管理,可借助阿里云的容器镜像服务 ACR来存储我们的镜像。
.gitlab-ci.yml
# 定义全局变量
variables:
DOCKER_IMAGE_NAME: $CI_PROJECT_NAME # 采用项目名作为镜像名
DOCKER_REGISTRY_USERNAME: username # 阿里云主账号名
DOCKER_REGISTRY_PASSWORD: password # 容器服务设置的密码
DOCKER_REGISTRY: registry.cn-hangzhou.aliyuncs.com # 按自己的镜像仓库公网地址配置,这里为杭州节点地址
DOCKER_NAMESPACE: namespace # 按自己创建的命名空间设置
DOCKER_IMAGE_NAME: $DOCKER_REGISTRY/$DOCKER_NAMESPACE/$CI_PROJECT_NAME # 采用项目名作为镜像名
DOCKER_IMAGE_TAG: $DOCKER_IMAGE_NAME:$CI_COMMIT_TAG # 采用镜像名+项目tag作为最终镜像版本
# 公共的 docker login 配置
.docker-login: &docker-login
before_script:
- export
- echo ${DOCKER_REGISTRY_PASSWORD} | docker login -u ${DOCKER_REGISTRY_USERNAME} --password-stdin ${DOCKER_REGISTRY}
docker-build:
stage: docker-build
image: docker:latest
<<: *docker-login
script:
- export
- docker build -t ${DOCKER_IMAGE_TAG} .
- docker push ${DOCKER_IMAGE_TAG} # 推送镜像至阿里云
dependencies:
- build
only:
- /^rc-.*/
deploy:
stage: deploy
image: docker:latest
<<: *docker-login
script:
- export
- docker-compose -f docker-compose.yaml pull # 从阿里云拉取镜像
- docker-compose -f docker-compose.yaml up -d
only:
- /^rc-.*/
when: manual
添加旧镜像清理操作
清理镜像思路:
正常的删除镜像命令docker rmi
,在删除正在使用的镜像时,会报错。
而docker image prune
命令可以清理所有悬空镜像,且:
- 添加
-a
参数,可以清理所有未使用的镜像 - 添加
-f
参数,可以强制清理不在询问 - 通过
--filter "label=[key]=[value]"
可以筛选镜像中指定标签为指定值的镜像。
通过在构建镜像时指定特殊标签,并配合docker image prune -a -f --filter "label=[key]=[value]"
命令,完全符合清理指定项目未使用的过期镜像的目的。
Dockerfile
# 使用nginx-alpine作为基础镜像
FROM nginx:1.28.0-alpine3.21
# 定义构建参数
ARG PROJECT_NAME
# 添加项目标签
LABEL project="${PROJECT_NAME}"
# 复制构建后的文档到nginx的默认目录
COPY docs/.vuepress/dist/ /usr/share/nginx/html/
# 复制自定义nginx配置
COPY nginx.conf /etc/nginx/nginx.conf
# 暴露80端口
EXPOSE 80
# 启动nginx
CMD ["nginx", "-g", "daemon off;"]
.gitlab-ci.yml
docker-build:
script:
- docker build -t ${DOCKER_IMAGE_TAG} .
- docker build --build-arg PROJECT_NAME=${CI_PROJECT_NAME} -t ${DOCKER_IMAGE_TAG} . # 通过--build-arg添加变量作为项目名
deploy:
script:
- docker-compose -f docker-compose.yaml up -d
- docker image prune -a -f --filter "label=project=${CI_PROJECT_NAME}" # 强制清理指定标签下所有未使用的镜像