Skip to content

在线文档

笔记对应的代码

将项目部署到 GitLab Pages

说明: 跟 Github Actions 一样还是部署 vitepress 项目

注意:

公司内部的文档项目可能是这样部署的, 如果用的是社区免费版本自建的 gitlab 服务器, 那么需要登录管理员去开启 Pages 功能, 因为 Pages 功能默认是关闭的, 如果只是学习 的话, 建议直接使用 gitlab.com

1.修改 vitepress 配置

修改 outDir 字段, 参考官方文档

js
export default {
  outDir: '../public',
};

注意与 Github Pages 的不同, 不需要设置 base 字段

因为 Github Pages 生成的域名是这样的 https://<user-name>.github.io/<repo-name>

而 GitLab pages 生成的域名是这样的 https://<repo-name>-<username>-<hash>.gitlab.io

所以 Github Pages 是必须设置 base 字段的, 但是 GitLab Pages 是不需要的, 你可以查看 vitepress 文档

  • <user-name>: 平台账号名
  • <repo-name>: 仓库名
  • <hash>: 随机30位字符串

为什么要修改 outDir 字段?

经测试, 不改成 ../public 无法部署成功, 所以就必须设置 vitepress 打包结果输出目录

2.创建 gitlab CICD 配置文件

在项目根目录下新建 .gitlab-ci.yml 内容如下:

参考 vitepress 文档

yml
# 配置文件字段可参考: https://docs.gitlab.cn/jh/ci/yaml/gitlab_ci_yaml.html
# 使用的容器: https://hub.docker.com/_/node
# 使用的容器的版本tag: 18
image: node:18

# 定义阶段
stages:
  - build
  - deploy

# 缓存: 会计算 package.json 的 md5 值, 如果没有变化就使用缓存
cache:
  key:
    files:
      - package.json
  paths:
    - node_modules

# 定义任务(必须叫这个名字): 发布到 Gitlab Pages
pages:
  stage: build
  script: |
    npm install 
    npm run docs:build
    echo "===== build completed =====";

  # 产出的结果
  artifacts:
    paths:
      - ./public

  # 当提交 main 分支代码的时候执行
  only:
    - main
yml
image: node:18
pages:
  cache:
    paths:
      - node_modules/
  script:
    # - apk add git # Uncomment this if you're using small docker images like alpine and have lastUpdated enabled
    - npm install
    - npm run docs:build
  artifacts:
    paths:
      - public
  only:
    - main

3. 运行&查看 gitlab runner 执行和输出

将项目部署到服务器

0.准备步骤

  1. 准备一台公网能够访问的服务器
  2. gitlab cicd 有大致的了解
  3. 了解 linux 命令
  • tar: 压缩需要的文件(目标服务器上必须要安装这个命令, 一般都自带有)
  • sshpass: 替换 ssh 命令功能, 因为ssh命令是交互式的, 不太适合自动执行命令
  • scp: 上传文件到目标服务器

1.修改 .vitepress 配置

如果已经修改过就不用再修改了, 虽然不修改目录也能部署, 但是为了和前面 部署到 GitLab Pages 保持一致, 还是修改下

js
export default {
  outDir: '../public',
};

2.创建 cicd variables

就是类似 github 的那个 Repository Secrets, 功能是一样的, 名字不同, 都是给配置文件提供变量来存储一些不方便暴露配置

3.创建 cicd 流水线配置文件

在项目的根目录下创建 .gitlab-ci.yml 配置文件

yml
image: node:18

# 定义阶段
stages:
  - build
  - deploy

# 缓存(不要重复下载 node_modules)
cache:
  key:
    files:
      - package.json
  paths:
    - node_modules

# 发布到 gitlab-pages(提交 main 分支的时候执行)
pages:
  stage: build
  script: |
    npm install 
    npm run docs:build
    echo "===== build completed =====";

  artifacts:
    paths:
      - ./public
  only:
    - main

# 定义任务(build_jobs)
build_jobs:
  stage: build
  script: |
    # 安装依赖
    npm install 

    # 压缩需要的文件
    npm run docs:build

    # 压缩需要的文件到一个压缩包中
    tar -zcvf artifacts.tar ./run.sh ./public/*
    ls -al
    echo "===== build completed =====";

  # 定义产出文件路径
  artifacts:
    paths:
      - ./artifacts.tar

  # 定义触发条件: 在提交 deploy2server 分支的时候执行
  only:
    - deploy2server

# 定义任务(deploy_jobs):  将 build_jobs 产出的结果部署到指定服务器
deploy_jobs:
  # 在 deploy 阶段执行
  stage: deploy

  # 定义触发条件: 在提交 deploy2server 分支的时候执行
  only:
    - deploy2server

  # 使用这个镜像就可以直接使用 sshpass 命令
  image: ringcentral/sshpass:latest
  script: |
    ls -al

    # 1.清除上次构建缓存(如果构建多次的话)
    echo "===== 1.start deployment ====="
    sshpass -p $SERVER_PASS ssh -o StrictHostKeyChecking=no -p$SERVER_PORT $SERVER_USER@$SERVER_ADDR "rm -rf ~/deploy-dir && mkdir ~/deploy-dir"

    # 2.上传产出文件(压缩包)到服务器(注意文件名和目标服务器的路径)
    # 注意: scp 命令 -P参数是大写, 必须是: "-P22" ,不能是 "-p22"
    # 否则会将 "22" 当作文件来上传, 就会导致找不到这个文件而报错
    echo "===== 2.start upload files ====="
    sshpass -p $SERVER_PASS scp -o StrictHostKeyChecking=no -P$SERVER_PORT ./artifacts.tar $SERVER_USER@$SERVER_ADDR:~/deploy-dir/artifacts.tar
    echo "===== 3.upload completed ====="

    # 3.解压缩
    sshpass -p $SERVER_PASS ssh -o StrictHostKeyChecking=no -p$SERVER_PORT $SERVER_USER@$SERVER_ADDR "cd ~/deploy-dir && tar -zxvf ./artifacts.tar"
    echo "===== 4.unzip completed ====="

    # 4.执行 run.sh 这个 shell 脚本
    sshpass -p $SERVER_PASS ssh -o StrictHostKeyChecking=no -p$SERVER_PORT $SERVER_USER@$SERVER_ADDR "cd ~/deploy-dir && chmod +x ./run.sh && ./run.sh"
    echo "===== 5.deploy completed ====="

为什么要将命令分这么多步骤, 并且输出?

因为是学习阶段, 还不熟练, 为了好排查错误, 如果报错了, 就知道到底是哪个步骤报错了, 当写熟练了之后, 就可以不用怎么繁琐了

4.创建执行部署的 shell 脚本

在项目的根目录下创建 run.sh

sh
#!/bin/bash

# 定义docker 镜像名 和 容起名 变量
docker_container_name="learn-gitlab-runner-demo"
docker_image_name="nginx:stable"

# 先停止原来的
docker stop $docker_container_name
docker rm $docker_container_name

# 启动容器(注意路径)
docker run -d \
	-p 80:80 \
	-v $(pwd)/public:/usr/share/nginx/html \
	--name $docker_container_name $docker_image_name

5.执行/查看流水线任务

注: 必须提交代码到 deploy2server 这个分支才能执行, 因为触发条件是写在 .gitlab-ci.yml 文件中的

扩展: 使用 ssh 私钥链接服务器

为什么我没有用这种方式来操作?

因为用用户名密码的方式更直观, 做笔记利于阅读, 但是在那个 learn-gitlab-cicd-demo 项目中, 有个 deploy_with_ssh_key 分支, 里面有对应的注释和示例

如果要在 gitlab 中使用私钥链接服务器, 在添加 cicd variables 的时候必须要在私钥的内容最后添加一行空格,否则会报错,密钥格式有误

yml
image: node:18

stages:
  - build
  - deploy

cache:
  key:
    files:
      - package.json
  paths:
    - node_modules

# 打包任务
build_jobs:
  stage: build
  script: |
    npm install 
    npm run docs:build
    tar -zcvf artifacts.tar ./run.sh ./public/*
    ls -al
    echo "===== build completed =====";

  artifacts:
    paths:
      - ./artifacts.tar
  only:
    - deploy2server
    - deploy_with_ssh_key

# 发布到指定服务器, 并且使用 ssh private key
deploy_with_ssh_key_jobs:
  # 在部署阶段执行
  stage: deploy

  # 提交 deploy_with_ssh_key 分支的时候执行
  only:
    - deploy_with_ssh_key

  # 在 ubuntu 镜像中完成这些操作
  image: ubuntu
  before_script:
    ## 安装 openssh 客户端和 git
    - which ssh-agent || ( apt-get update -y && apt-get install openssh-client git -y )

    ## 添加 private key
    - mkdir -p ~/.ssh
    - eval "$(ssh-agent -s)"
    - ssh-add <(echo "$SSH_PRIV_KEY")

    ## 添加 known_hosts
    - ssh-keyscan -H "$SERVER_ADDR" >> ~/.ssh/known_hosts

    ## 修改 ssh 配置
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config
  script: |
    ls -al
    echo "===== 1.start deployment ====="
    ssh -p$SERVER_PORT $SERVER_USER@$SERVER_ADDR "rm -rf ~/deploy-dir && mkdir ~/deploy-dir"
    echo "===== 2.start upload files ====="
    scp -P$SERVER_PORT ./artifacts.tar $SERVER_USER@$SERVER_ADDR:~/deploy-dir/artifacts.tar
    echo "===== 3.upload completed ====="
    ssh -p$SERVER_PORT $SERVER_USER@$SERVER_ADDR "cd ~/deploy-dir && tar -zxvf ./artifacts.tar"
    echo "===== 4.unzip completed ====="
    ssh -p$SERVER_PORT $SERVER_USER@$SERVER_ADDR "cd ~/deploy-dir && chmod +x ./run.sh && ./run.sh"

使用自建的 Gitlab

因为很多公司服务器是自己搭建 gitlab 服务器, 一是为了安全, 二是为了更好的性能

gitlab.com 提供的 runner 使用限制比较大, 而且服务器在国外部署的时候速度会比较慢

GitLab CICD 的执行原理

gitlab 是无法直接运行流水线任务的, 它必须要通过一个 gitlab-runner 的软件来运行, 如下图

使用 docker-compose 自建 gitlab 服务器

需要确保服务器已经安装了 docker 和 docker-compose

1. 创建 docker-compose.yml, 内容如下:

yml
version: '3.6'

services:
  gitlab-web:
    image: 'gitlab/gitlab-ce:15.11.13-ce.0'
    container_name: gitlab-web
    restart: always
    hostname: 'gitlab.liaohui5.cn'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.liaohui5.cn'
        gitlab_rails['gitlab_shell_ssh_port'] = 2233
    ports:
      - '4433:443'
      - '2233:22'
    volumes:
      - './config:/etc/gitlab'
      - './logs:/var/log/gitlab'
      - './data:/var/opt/gitlab'
    shm_size: '256m'

  gitlab-runner:
    image: 'gitlab/gitlab-runner:ubuntu-v15.11.0'
    restart: always
    container_name: gitlab-runner
    depends_on:
      - gitlab-web
    privileged: true
    volumes:
      - ./gitlab-runner-config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
      - /bin/docker:/bin/docker

2. 注意修改 /var/run/docker.sock 的权限

sh
chmod 777 /var/run/docker.sock

3. 启动服务

这个时间可能比较久(具体需要多久, 取决于服务器的性能)

sh
docker up -d

4. 获取 root 账户密码

注: 一定要记得重新设置 root 密码, 这个文件会在 24 小时后消失

sh
# gitlab-web: 是你的容器名
sudo docker exec -it gitlab-web grep 'Password:' /etc/gitlab/initial_root_password

5.修改 root 账户密码

注册 Runner

注意: 在注册之前, 最好是先获取注册 runner 需要的参数: gitlab url registration token

  • gitlab instance url: 就是你的 gitlib 的网址, 如: https://gitlab.example.com
  • registration token: 是必须的参数, token 可以让 github-runner 识别, 注册的是什么类型的 runner(全局/某个项目/某个组)

如何注册全局共享 runner?

需要管理员权限, 才能注册, 需要更多信息, 请查看文档

如何注册项目专属的 Runner?

不要随便执行你不信任的 runner, 最好只执行自己服务器上的 runner

执行注册

sh
docker run --rm -v ./gitlab-runner-config:/etc/gitlab-runner gitlab/gitlab-runner:ubuntu-v15.11.0 register
  --non-interactive \
  --url "https://gitlab.example.com/" \       # 你的 gitlab 地址
  --registration-token "your-token-string" \  # 你的 registration token
  --description "docker-runner" \             # runner的描述
  --tag-list "docker,aws" \                   # runner的标签列表,用逗号隔开
  --executor "docker" \                       # runner执行方式(推荐docker)
  --docker-image node:18 \                    # runner基于的镜像
  --run-untagged="true" \
  --locked="false" \
  --access-level="not_protected"

扩展使用自建的 gitea

Released under the MIT License.