Home
avatar

.Wang

OneDev通过CICD上线项目

近期在开发项目的时候,发现一个问题就是服务器的 CPU 时不时的飙的老高,内存占用也很大。于是将服务器升级为 4 核 8GB 内存,但是在部署项目的时候还是时不时的出现问题。

因为我的服务器上安装了将近 15 个 docker 容器,以及 15 个网站,对应的还有一些备份计划。于是我将系统的备份以及快照分布在七牛上了。这样也会降低内存风险。

因为使用的数据库,没有使用远程数据,所以数据的内存以及备份也会放在服务器,这样同样也会增加内存风险。

于是我在不动备份数据,以及不增加成本的情况下,将一些占用 cpu 高的容器优化整理如下:

  1. gitea 容器
  2. jenkins 容器

于是,我在我将二者合一替换为oneDev容器。oneDev容器支持 git 自托管,CICD 等功能。这样一个容器就可以替换掉 gitea 容器以及 jenkins 容器了。

接下来我将整理总结一下oneDev容器的使用经验。

安装

首先我使用的1panel面板来安装oneDev容器。

如果发现应用商店中没有对应的容器,那么有一个方法可以使用脚本文件进行应用商店应用的扩展。脚本如下:

# 更新三方应用库
git clone -b localApps https://github.com/okxlin/appstore /opt/1panel/resource/apps/local/appstore-localApps
cp -rf /opt/1panel/resource/apps/local/appstore-localApps/apps/* /opt/1panel/resource/apps/local/
rm -rf /opt/1panel/resource/apps/local/appsatore-localApps
echo 'ok'

之后更新之后,就可以在应用商店中看到oneDev容器了。 之前我想打算使用gitlab的,只是因为gitlab的容器比较大,占用的内存比较多,而oneDev容器占用的内存比较少。

可以使用域名代理访问oneDev容器。

使用

x 如图所示,这是我现在的oneDev容器的使用界面。

刚开始使用的时候,我也研究了一下,这款软件不错,还可以设置中英文语言。总体功能还算齐全。

当然可以自己创建项目,同时也支持远程仓库的导入。导入完成后,可以使用配置进行 CICD 的配置。文件名为:.onedev-buildspec.yml,这个文件类似于githubactions文件, 如下图:

x

这里有一个配置:

version: 43
jobs:
  - name: 打包部署
    steps:
      - type: UseTemplateStep
        name: checkout code
        templateName: 代码签出
        condition: SUCCESSFUL
        optional: false
      - type: UseTemplateStep
        name: generate package checksum
        templateName: 生成软件包校验
        condition: SUCCESSFUL
        optional: false
      - type: UseTemplateStep
        name: set up npm cache
        templateName: 生成缓存
        condition: SUCCESSFUL
        optional: false
      - type: UseTemplateStep
        name: set up npm cache
        templateName: 构建版本
        condition: SUCCESSFUL
        optional: false
      - type: UseTemplateStep
        name: build & upload
        templateName: 上传构建产物
        condition: SUCCESSFUL
        optional: false
      - type: UseTemplateStep
        name: product
        templateName: 生成制品
        condition: SUCCESSFUL
        optional: false
      - type: UseTemplateStep
        name: deploy
        templateName: 部署
        condition: SUCCESSFUL
        optional: false
    triggers:
      - type: BranchUpdateTrigger
        branches: master
        userMatch: anyone
    retryCondition: never
    maxRetries: 3
    retryDelay: 30
    timeout: 14400
stepTemplates:
  - name: 代码签出
    steps:
      - type: CheckoutStep
        name: checkout code
        cloneCredential:
          type: DefaultCredential
        withLfs: false
        withSubmodules: false
        condition: SUCCESSFUL
        optional: false
  - name: 生成软件包校验
    steps:
      - type: GenerateChecksumStep
        name: generate package checksum
        files: package-lock.json yarn.lock pnpm-lock.yaml
        targetFile: checksum
        condition: SUCCESSFUL
        optional: false
  - name: 生成缓存
    steps:
      - type: SetupCacheStep
        name: set up npm cache
        key: node_modules_@file:checksum@
        loadKeys:
          - node_modules
        paths:
          - node_modules
        uploadStrategy: UPLOAD_IF_NOT_HIT
        condition: SUCCESSFUL
        optional: false
  - name: 构建版本
    steps:
      - type: SetBuildVersionStep
        name: set build version
        buildVersion: "@script:builtin:node:determine-project-version@"
        condition: SUCCESSFUL
        optional: false
  - name: 上传构建产物
    steps:
      - type: CommandStep
        name: build & upload
        runInContainer: true
        image: node
        interpreter:
          type: DefaultInterpreter
          commands: |
            set -e

            echo "📦 开始进行构建..."
            # 构建
            npm install -g pnpm
            pnpm install
            pnpm run build
            echo "✅ 构建完成..."

            echo "🌾 开始进行同步ssh..."
            # 同步ssh
            mkdir -p ~/.ssh
            chmod 700 ~/.ssh
            # 使用 printf 或 echo -e 来写入私钥,避免 heredoc 问题
            printf '%s\n' '@secret:ssh@' > ~/.ssh/id_rsa
            chmod 600 ~/.ssh/id_rsa
            # 验证私钥格式
            if ssh-keygen -l -f ~/.ssh/id_rsa > /dev/null 2>&1; then
              echo "✅ 私钥格式验证通过"
            else
              echo "❌ 私钥格式错误"
              exit 1
            fi

            ssh-keyscan -H 你的服务器IP >> ~/.ssh/known_hosts
            chmod 644 ~/.ssh/known_hosts
            echo "✅ ssh同步完成..."

            echo "⏫ 开始上传构建产物..."
            CACHE_DIR="/opt/build_cache_apps/plugin-functional-helpers"
            ssh -o StrictHostKeyChecking=no -o BatchMode=yes 你的用户名@你的服务器IP "mkdir -p $CACHE_DIR"
            scp -o StrictHostKeyChecking=no -o BatchMode=yes -r dist/* 你的用户名@你的服务器IP:$CACHE_DIR/
            echo "✅ 构建产物上传完成..."
        useTTY: true
        condition: SUCCESSFUL
        optional: false
  - name: 生成制品
    steps:
      - type: PublishArtifactStep
        name: Products
        sourcePath: dist
        artifacts: "**"
        condition: SUCCESSFUL
        optional: false
  - name: 部署
    steps:
      - type: SSHCommandStep
        name: deploy
        remoteMachine: 你的服务器IP
        userName: root
        privateKeySecret: ssh
        commands: |
          echo "🪤 开始进行项目部署..."
          # 临时的构建产物目录
          CACHE_DIR="/opt/build_cache_apps"
          # 容器名
          CONTAINER_NAME="openresty"
          # 目标路径
          CONTAINER_PATH="/www/sites"
          # 在容器中创建目录并复制文件
          # docker exec $CONTAINER_NAME mkdir -p $CONTAINER_PATH
          docker cp $CACHE_DIR/. $CONTAINER_NAME:$CONTAINER_PATH
          echo "✅ 项目「plugin-functional-helpers」部署完成"

          echo "🧹 正在清理缓存..."
          rm -rf $CACHE_DIR
          echo "✅ 缓存已清除"
        condition: SUCCESSFUL
        optional: false

密钥的生成

其中的 ssh 密钥是用来进行服务器之间的 ssh 连接的,需要在服务器上生成一个密钥对,将公钥配置到服务器上,私钥配置到 onedev 中。如图:

服务器 ssh 中执行:

# 生成密钥对
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# 复制公钥到服务器
ssh-copy-id 你的用户名@你的服务器IP

# 如果 ssh-copy-id 失败,手动复制公钥
cat ~/.ssh/id_rsa.pub | ssh 你的用户名@你的服务器IP "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# 完成之后,可以查看服务器 ~/.ssh/authorized_keys 文件是否包含了你的公钥
cat ~/.ssh/authorized_keys

# 这一行解释:
# 这行命令将本地的 dist 目录下的所有文件递归复制到服务器的 $CACHE_DIR 目录下。
# -o StrictHostKeyChecking=no 选项禁用主机密钥检查,这在第一次连接未知主机时很有用。
# -o BatchMode=yes 选项启用批量模式,这在脚本中执行时很有用,避免交互式提示。
scp -o StrictHostKeyChecking=no -o BatchMode=yes -r dist/* 你的用户名@你的服务器IP:$CACHE_DIR/

完成之后,可以在图中的这个地方查看:

这样有个好处就是:之前都是先将代码上传到 git 托管上,然后在通过 jenkins 进行发布,现在是直接在 onedev 上进行发布,省去了中间的步骤,当然可以设置代码合并策略,比如合并到主分支后触发发布。具体其他的可以自行研究。

服务器运维 CICD onedev

同系列的博文

Jenkins的使用(一)
服务器运维Jenkins

Jenkins的使用(一)

Jenkins的使用(二)
服务器运维Jenkins

Jenkins的使用(二)

Docker打包项目上线
服务器运维Docker

Docker打包项目上线

设置