banner
innei

innei

写代码是因为爱,写到世界充满爱!
github
telegram
twitter

自建 Drone 绑定 GitHub 实现 CI/CD

群友说的我站点访问太慢。

因为部署在 Vercel 上,API 接口又在国内,通过 Zero 又套了一层,两层下来在国内的访问确实不是很好。

打算做一个在国内的镜像站。

原本 Kami 是通过 GitHub Actions 做的,通过发版然后把产物发布到 Release,SSH 连接到服务器之后再去拉取 GitHub Release,但是因为国内服务器现在访问 GitHub 真的太慢了,各大国内加速站也陆续挂壁了。

所以打算利用家用小主机完成本地部署,最后产物推送到云服务器。

问了群友之后,Drone CI 应该是是个不错的选择,Go 写的比较快也很轻量,可以非常简单和 GitHub 绑定。

总体的流程大概如下:

Mermaid Loading...

流程比较简单,接下来看看如何从零开始自建 Drone 和编写这个流程。

Drone 部署#

Docker Compose 一把梭#

全程使用:Arch Linux + Docker 环境,其他环境仅供参考。

官方文档写的比较散,这里我踩了很多坑。但是最后的配置的也没有什么特别的,我就直接贴这里了。

name: drone
services:
    drone-runner:
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
        environment:
            - DRONE_RPC_PROTO=https
            - DRONE_RPC_HOST=drone.innei.in
            - DRONE_RUNNER_CAPACITY=2
            - DRONE_RUNNER_NAME=runner

            - DRONE_GITHUB_CLIENT_ID=
            - DRONE_GITHUB_CLIENT_SECRET=
            - DRONE_RPC_SECRET=
            - DRONE_SERVER_HOST=
            - DRONE_SERVER_PROTO=https
        ports:
            - 3000:3000
        restart: always
        container_name: runner
        image: drone/drone-runner-docker:1
    drone:
        volumes:
            - ./data:/data
        environment:
            - DRONE_GITHUB_CLIENT_ID=
            - DRONE_GITHUB_CLIENT_SECRET=
            - DRONE_RPC_SECRET=
            - DRONE_SERVER_HOST=drone.innei.in
            - DRONE_SERVER_PROTO=https
            - DRONE_TLS_AUTOCERT=true
            - DRONE_USER_CREATE=username:innei,machine:false,admin:true
        ports:
            - 80:80
            - 443:443
        restart: always
        container_name: drone
        image: drone/drone:2
        networks:
          mvlan:
            ipv4_address: 10.0.0.47

networks:
  mvlan:
    external: true

上面配置缺失的环境变量需要去阅读文档,期间还需要创建一个自己的 GitHub App。

参考:

Runner 别忘了,我就是因为忘了配置 Runner,倒是 CI 一直都在 Loading 状态。

Drone 和 GitHub 连接是需要一个域名的(如果你没有域名可以试试用内网 IP 的方式),因为 oauth 的方式,验证成功之后会跳转回你设定的地址。我这里是 drone.innei.in。后续都按这个进行。

公网打洞#

上面配置之后,在内网 10.0.0.47 去登录是无法登陆的,通过 GitHub oauth 之后会跳回配置的 drone.innei.in,但是这个地址我没还配。

我使用 Cloudflare Zero Trust 进行打洞。非常方便。

image

这样就好了。

image

进去之后,面板是空空的。这个没有关系。到此 Drone 就搞定了。

Pipeline 编写#

来到需要跑 CI 的 GitHub 仓库,建立一个 .drone.yml 文件在根目录,然后 push 到 GitHub,此时 drone 应该会出现这个 Repo,进入之后激活他。

kind: pipeline
name: build-and-package
platform:
  os: linux
  arch: amd64

steps:
  - name: build
    image: node:20-alpine
    commands:
      - 'npm i -g pnpm'
      - 'pnpm install --no-frozen-lockfile'
      - 'npm run build'

这步成功之后接下来就就是疯狂调 pipeline 了。

由于 NextJS build 时候需要 .env 但是我又不想一个一个传到 secrets,他不支持批量导入(能不能学学隔壁 Vercel),所以我想如何另一种方式传入 env。这里也花了很多时间。

首先想过用 http-server 托管 .env ,在 build 去下载它,因为在内网监听,相对还是安全。后来发现 Drone 的 volume 映射可行,如果现在就用这个方案了。

Note

要使用 Volume 映射,你需要开启 Trusted 选项。

在做这一步你需要先开启管理员权限。如果是 docker 部署的,需要添加 ENV 到 Drone Server 中。 DRONE_USER_CREATE=username:innei,machine:false,admin:true username 替换为 GitHub 用户名。

重启容器后,再次进入 Drone 的 Repo Settings,会看到 Project Settings - Trusted 然后打开它。

image

我这里选择的是,Drone 在每个步骤都是 Docker 运行时。

在每个 step 都可以映射一个 volume 到宿主机文件路径。

我把项目需要的 .env 存放在 /home/innei/docker-compose/drone/public/shiro/.env ,在 build 的 step 添加 volume 映射。

volumes:
  - name: shiro-env
    host:
      path: /home/innei/docker-compose/drone/public/shiro/.env

steps:
  - name: build
    image: node:20-alpine
    commands:
      - 'npm i -g pnpm'
      - 'pnpm install --no-frozen-lockfile'
      - 'npm run build'

    volumes:
      - name: shiro-env
        path: /drone/src/.env

volumes 需要写两次,顶层的 volume 定义宿主机的绝对路径和 volume 名称,在 step 处则是 docker 重启的绝对路径。

我们可以把 build 和 deploy 拆分成两个 pipeline。但是前后依赖。

然后 build 完成之后,需要产物临时存储。我选择用 volume 方式,临时放在 /tmp 下,供 deploy 获取产物以推送到云服务器。

volumes:
  - name: shiro-dist
    host:
      path: /tmp/shiro-dist
      
steps:
  - name: build
    image: node:20-alpine
    commands:
      - 'npm i -g pnpm'
      - 'pnpm install --no-frozen-lockfile'
      - 'npm run build'

    volumes:
      - name: shiro-env
        path: /drone/src/.env
      - name: dns
        path: /etc/resolv.conf

  - name: package
    image: node:20-alpine
    commands:
      - 'pwd'
      - 'ls -a'
      - 'ls .next'
      - 'apk add zip'
      - 'sh ./standalone-bundle.sh'
    volumes:
      - name: shiro-dist      # 这里映射
        path: /drone/src/assets

    depends_on:
      - build

然后在 deploy 使用 scp 和 ssh 。

ind: pipeline
name: deploy
platform:
  os: linux
  arch: amd64

volumes:
  - name: shiro-dist
    host:
      path: /tmp/shiro-dist

steps:
  - name: transfer file
    image: appleboy/drone-scp
    settings:
      host:
        from_secret: ssh_host
      username:
        from_secret: ssh_username
      key:
        from_secret: ssh_key
      port: 22
      target: /home/deploy/shiro
      source:
        - assets/release.zip
      rm_target: true
      strip_components: 1
      debug: true
    volumes:
      - name: shiro-dist  # 这里 volume 可以获取到 build pipeline 的产物
        path: /drone/src/assets

  - name: deploy
    image: appleboy/drone-ssh
    settings:
      host:
        from_secret: ssh_host
      username:
        from_secret: ssh_username
      key:
        from_secret: ssh_key
      port: 22
      script:
        - '\npm install --os=linux --cpu=x64 sharp --registry=https://registry.npmmirror.com'
        - cd ~/shiro
        - unzip -o release.zip
        - rm release.zip
        - ls
        - cd standalone
        - cp -r ~/node_modules/sharp ./node_modules
        - ~/.n/bin/pm2 restart ecosystem.config.js
      debug: true
    depends_on:
      - transfer file

depends_on:
  - build-and-package # 这里依赖

ssh_ 相关的则从 secrets 中获取。

至此结束,我也就尝试了四十几周目😂。

image

成品配置#

https://github.com/Innei/Shiro/blob/main/.drone.yml

参考:https://www.timochan.cn/posts/jc/drone_workflows#Preface

此文由 Mix Space 同步更新至 xLog
原始链接为 https://innei.in/posts/Z-Turn/drone-self-host-ci-cd-with-github


加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。