基于gitea+drone完成小团队的CI/CD

2022-10-31 14:47:15 浏览数 (1)

前言

持续集成和构建的工具有很多,除了著名的 Jenkins,Travis,CircleCI,还有最近比较热门的 Github Action 和 Gitlab CI/CD。但是这些工具面对私人项目不是要收费就是占用大量服务器资源,作为个人开发者的私人项目如果想要使用并不友好。那么开源免费的 Drone CI 是个不错选择,它不但非常轻量,而且十分强大。并可以结合私有代码仓库自动编译、构建服务,几行脚本即可实现自动化部署。本文讲述 Drone CI 的具体实践,结合Gitea,怎么在 VPS 里从零开始搭建一个基于 Gitea Drone CI 的持续集成系统。

Gitea 简介

Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证

Gitea的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。采用Go作为后端语言,只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了x86,amd64,还包括 ARM 和 PowerPC.

Gitea 功能特性

  • 支持活动时间线
  • 支持 SSH 以及 HTTP/HTTPS 协议
  • 支持 SMTP、LDAP 和反向代理的用户认证
  • 支持反向代理子路径
  • 支持用户、组织和仓库管理系统
  • 支持添加和删除仓库协作者
  • 支持仓库和组织级别 Web 钩子(包括 Slack 集成)
  • 支持仓库 Git 钩子和部署密钥
  • 支持仓库工单(Issue)、合并请求(Pull Request)以及 Wiki
  • 支持迁移和镜像仓库以及它的 Wiki
  • 支持在线编辑仓库文件和 Wiki
  • 支持自定义源的 Gravatar 和 Federated Avatar
  • 支持邮件服务
  • 支持后台管理面板
  • 支持 MySQL、PostgreSQL、SQLite3、MSSQL 和 TiDB(MySQL) 数据库
  • 支持多语言本地化(21 种语言)

Drone 简介

Drone 是一款基于 Docker 的 CI/CD 工具,所有编译、测试、发布的流程都在 Docker 容器中进行.

开发者只需在项目中包含 .drone.yml 文件,将代码推送到 git 仓库,Drone 就能够自动化的进行编译、测试、发布。

为什么使用 Drone 作为CI/CD 工具

  • 功能灵活强大:构建、测试、发布、部署,你想干什么都可以,一套系统全搞定
  • 兼容性好:支持所有SCM、所有平台、所有语言
  • 环境部署简单:原生支持Docker容器,启动两个容器就完成了部署,其它构建、测试、部署工具在使用时会自动从docker仓库拉取
  • 扩展性强:强大的插件系统,丰富的插件可以免费使用,也可以自定义
  • 配置简单:正如官方宣传的那样,“configuration as a code”,所有功能、步骤、工具、命令,一个yaml配置文件全搞定
  • 维护简单:直接复用SCM的账号体系和权限管理,无需注册用户、分配权限

安装前准备

docker环境安装

1、首先到各大公有云厂商提供的云平台上购买对应的机器,配置可以选择1核2g,或者2核2g,不需要购买太大的配置。

2、机器开通完成后,部署docker环境,可以选择手动部署,或者使用Ansible脚本部署,本次使用Ansible部署,部署脚本如下:(docker-install.yaml)

代码语言:yaml复制
---

- name: Remove Docker system
  yum:
    name:
    - docker-client
    - docker-client-latest
    - docker-common
    - docker-latest
    - docker-latest-logrotate
    - docker-logrotate
    - docker-selinux
    - docker-engine-selinux
    - docker-engine
    state: absent
  tags:
  - cicd
  - docker_remove

- name: Remove Docker files
  shell: |
    rm -rf /etc/systemd/system/docker.service.d
    rm -rf /var/lib/docker
    rm -rf /var/run/docke
    rm -rf /etc/docker    
  tags:
  - cicd
  - docker_remove

- name: Install Docker yum
  yum:
    name:
    - yum-utils 
    - device-mapper-persistent-data 
    - lvm2
    state: present
  tags:
  - cicd
  - docker_install

- name: Install yum manager
  shell: |
        yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  tags:
  - cicd
  - docker_install

- name: Install Docker
  yum:
    name: docker-ce
    state: present
  tags:
  - cicd
  - docker_install

- name: Configure Docker for files
  file:
    path: "{{ item }}"
    state: directory
  with_items:
  - /etc/docker
  - /etc/systemd/system/docker.service.d
  tags:
  - cicd
  - docker_install

- name: Configure Docker for config
  template:
    src: "{{ item.name }}"
    dest: "{{ item.dest }}"
  loop:
  - { name: "daemon.json.j2", dest: "/etc/docker/daemon.json" }
  - { name: "docker.service.j2", dest: "/usr/lib/systemd/system/docker.service" }
  tags:
  - cicd
  - docker_install

- name: Started Docker
  systemd:
    name: docker
    enabled: yes
    state: started
  tags:
  - cicd
  - docker_install

- name: Install Docker-Compose
  environment: 
    DOCKER_COMPOSE_VERSION: 1.25.0-rc2
  shell: |
    curl -L https://get.daocloud.io/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
    chmod  x /usr/local/bin/docker-compose    
  tags:
  - cicd
  - docker_install

- name: Install Docker Swarm
  shell:
    docker swarm init --advertise-addr {{ groups['pankuibo'][0] }}
  tags:
  - cicd
  - docker_install

3、安装docker环境,由于本次Ansible为剧本形式,所以执行如下命令来安装docker:

代码语言:shell复制
ansible-playbook --inventory-file='./../inventory/inventory.ini' ./deploy.yml -e target='test' --tags='docker_remove,docker_install,docker_compose' --forks=5 --user='root'

这里说明一下: 1、由于定义了不同的tags,来执行不同的操作 2、部署文件、主机文件、角色文件单独分开,更加灵活方便

Gitea安装及配置

安装

Gitea 在其 Docker Hub 组织内提供自动更新的 Docker 镜像。可以始终使用最新的稳定标签或使用其他服务来更新 Docker 镜像,安装的配置文件如下(docker-compose-gitea.yaml):

代码语言:yaml复制
version: "3.8"

services:
  gitea:
    image: gitea/gitea:1.16.5
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - DB_TYPE=mysql
      - DB_HOST=localhost:3306
      - DB_NAME=gitea
      - DB_USER=gitea
      - SSH_PORT=2224
    volumes:
      - /data/gitea:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2224:2224"
    networks:
      - "default"
    deploy:
      mode: replicated
      replicas: 1
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=default"
        - "traefik.http.services.gitea_gitea.loadbalancer.server.port=3000"
        # http 80
        - "traefik.http.routers.gitea.rule=Host(`gitea.localhost.com`)" 
        - "traefik.http.routers.gitea.entrypoints=web"
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
networks:
  default:
    external:
      name: traefik_default

由于依赖于数据库,所以需要先安装Mysql服务到环境中,使用Mysql的安装配置文件如下(docker-compose-mysql.yaml)

代码语言:yaml复制
version: "3.8"

services:
  mysql:
    image: mysql:5.7.37
    environment:
      - MYSQL_ROOT_PASSWORD=PWD
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - /data/mysql:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3306:3306"
    networks:
      - "default"
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
networks:
  default:
    external:
      name: traefik_default

要基于 docker-compose 启动gitea,请执行 docker-compose up -d,以在后台启动 Gitea。使用 docker-compose ps 将显示 Gitea 是否正确启动。可以使用 docker-compose logs 查看日志。

要停止gitea,请执行 docker-compose down。这将停止并杀死容器。这些卷将仍然存在。

本次使用如下命令来安装Gitea,目前环境中使用Docker Swarm集群,所以使用如下命令安装即可,关于Docker Swarm的使用说明可以参照Docker Swarm使用说明

代码语言:shell复制
1、docker stack deploy -c docker-compose-mysql.yaml mysql
2、docker stack deploy -c docker-compose-gitea.yaml gitea

以上设置中 Gitea 的端口号为 3000,因此本地环境浏览器进入localhost:3000即可访问页面,建议配置域名和 Nginx 或 Caddy 反向代理访问。本次使用的代理组件是traefik代理,更多关于traefik的使用说明请参考traefik使用说明

关于上面的配置说明

数据库

要将 Gitea 与 MySQL 数据库结合使用,请将这些更改应用于上面创建的 docker-compose-gitea.yaml 文件

代码语言:yaml复制
version: "3.8"

services:
  gitea:
    image: gitea/gitea:1.16.5
    environment:
       - DB_TYPE=mysql
       - DB_HOST=localhost:3306
       - DB_NAME=gitea
       - DB_USER=gitea
环境变量
  • APP_NAME:“Gitea: Git with a cup of tea”:应用程序名称,在页面标题中使用。
  • RUN_MODE:prod:应用程序运行模式,会影响性能和调试。“dev”,“prod"或"test”。
  • DOMAIN:localhost:此服务器的域名,用于 Gitea UI 中显示的 http 克隆 URL。
  • SSH_DOMAIN:localhost:该服务器的域名,用于 Gitea UI 中显示的 ssh 克隆 URL。如果启用了安装页面,则 SSH 域服务器将采用以下形式的 DOMAIN 值(保存时将覆盖此设置)。
  • SSH_PORT:22:克隆 URL 中显示的 SSH 端口。
  • SSH_LISTEN_PORT:%(SSH_PORT)s:内置 SSH 服务器的端口。
  • DISABLE_SSH:false:如果不可用,请禁用 SSH 功能。如果要禁用 SSH 功能,则在安装 Gitea 时应将 - SSH 端口设置为 0。
  • HTTP_PORT:3000:HTTP 监听端口。
  • ROOT_URL:"":覆盖自动生成的公共 URL。如果内部 URL 和外部 URL 不匹配(例如在 Docker 中),这很有用。
  • LFS_START_SERVER:false:启用 git-lfs 支持。
  • DB_TYPE:sqlite3:正在使用的数据库类型[mysql,postgres,mssql,sqlite3]。
  • DB_HOST:localhost:3306:数据库主机地址和端口。
  • DB_NAME:gitea:数据库名称。
  • DB_USER:root:数据库用户名。
  • DB_PASSWD:"” :数据库用户密码。如果您在密码中使用特殊字符,请使用“您的密码”进行引用。
  • INSTALL_LOCK:false:禁止访问安装页面。
  • SECRET_KEY:"" :全局密钥。这应该更改。如果它具有一个值并且 INSTALL_LOCK 为空,则 INSTALL_LOCK 将自动设置为 true。
  • DISABLE_REGISTRATION:false:禁用注册,之后只有管理员才能为用户创建帐户。
  • REQUIRE_SIGNIN_VIEW:false:启用此选项可强制用户登录以查看任何页面。
  • USER_UID:1000:在容器内运行 Gitea 的用户的 UID(Unix 用户 ID)。如果使用主机卷,则将其与 /data - 卷的所有者的 UID 匹配(对于命名卷,则不需要这样做)。
  • USER_GID:1000:在容器内运行 Gitea 的用户的 GID(Unix 组 ID)。如果使用主机卷,则将其与 /data 卷的所有者的 GID 匹配(对于命名卷,则不需要这样做)

创建新的 OAuth2 应用程序

创建一个Gitea的 OAuth2 应用程序,“客户端ID”和“客户端密钥”用于授权访问Gitea的资源。 重定向 URI配置必须按照下面示例的格式和路径,并且必须是真实存在的

  • 应用名称-Drone CI
  • 重定向URI-指向Drone的登陆URI
  • 客户端ID
  • 客户端密钥

Drone安装及配置

创建新的共享密钥

创建一个新的共享密钥,用于授权Runners和Drone Server之间进行通信。

可以使用openssl命令生成一个共享密钥:

代码语言:shell复制
openssl rand -hex 16
61379d57490fe37822267e7984acc934

下载镜像

Drone Server 以轻量级的Docker镜像的形式发布,镜像是自包含的,没有任何外部依赖。

代码语言:shell复制
docker pull drone/drone

配置

Drone 服务器使用环境变量进行配置。本文引用了配置选项的子集,定义如下。有关配置选项的完整列表,请参阅配置

Drone Server 部分

DRONE_GITEA_CLIENT_ID 必需的字符串值提供您的 Gitea oauth 客户端 ID

DRONE_GITEA_CLIENT_SECRET 必需的字符串值提供您的 Gitea oauth 客户端密码

DRONE_GITEA_SERVER 必需的字符串值提供您的 Gitea 服务器地址。例如https://gitea.company.com,请注意,http(s)否则您将看到来自 Gitea 的“不支持的协议方案”错误

DRONE_RPC_SECRET 必需的字符串值提供在上一步中生成的共享密钥。这用于验证服务器和运行器之间的 rpc 连接。必须为服务器和运行器提供相同的秘密值

DRONE_SERVER_HOST 必需的字符串值提供您的外部主机名或 IP 地址。如果使用 IP 地址,您可以包括端口。例如drone.company.com

DRONE_SERVER_PROTO 必需的字符串值提供您的外部协议方案。此值应设置为 http 或 https。如果您配置 ssl 或 acme,此字段默认为 https

DRONE_DATABASE_DATASOURCE

代码语言:shell复制
DRONE_DATABASE_DATASOURCE=root:password@tcp(1.2.3.4:3306)/drone?parseTime=true

可选的字符串值。配置数据库连接字符串。默认值为嵌入的 sqlite 数据库文件的路径

DRONE_DATABASE_DRIVER 可选字符串值。配置数据库驱动程序名称。默认值为 sqlite3 驱动程序。替代驱动程序是 postgres 和 mysql

DRONE_GITEA_SKIP_VERIFY 布尔值在建立与远程 Gitea 服务器的连接时禁用 tls 验证。默认值为假

DRONE_RUNNER_CAPACITY 可选数字值。限制运行器可以执行的并发管道的数量。这并不限制可以在单个远程实例上执行的并发管道的数量

DRONE_USER_CREATE

代码语言:shell复制
$ openssl rand -hex 16
55f24eb3d61ef6ac5e83d550178638dc
DRONE_USER_CREATE=username:octocat,machine:false,admin:true,token:55f24eb3d61ef6ac5e83d550178638dc

在启动时创建的可选用户帐户。这应该用于使用管理帐户为系统播种。它可以是真实账户(即真实的 GitHub 用户),也可以是机器账户

DRONE_USER_FILTER 可选的以逗号分隔的帐户列表。注册仅限于此列表中的用户,或属于此列表中组织成员的用户

Drone Runner 部分
  • DRONE_RPC_HOST 提供 Drone Server 的网络地址(可以带上端口号),Drone Runner 会根据地址连接到 Drone Server 以接收来自 Server 的 piplines 任务
  • DRONE_RPC_SECRET 提供在上一步中生成的共享密钥。这用于验证服务器和运行器之间的 rpc 连接。必须为服务器和运行器提供相同的秘密值
  • DRONE_RPC_PROTO 填http或者https。 取决于访问 Drone Server 的地址是否使用 https
  • DRONE_RUNNER_CAPACITY 一次可以执行几个job,不可为0
  • DRONE_RUNNER_NAME 可选的字符串值。设置Runnner的名字。Runner名称存储在服务器中,可用于将构建追溯到特定Runner
  • DRONE_RUNNER_LABELS 可选的字符串映射。提供一组标签,用于将管道路由到特定机器或一组机器
  • DRONE_LOGS_DEBUG 启用调试日志记录。此配置参数是布尔类型,是可选的
  • DRONE_LOGS_PRETTY 启用日志作为默认 json 格式的替代。此配置参数是布尔类型,是可选的
  • DRONE_LOGS_NOCOLOR 启用日志的颜色格式;与漂亮的打印日志一起使用。此配置参数是布尔类型,是可选的

安装Drone server 和 Drone Runner

Drone Runner 说明

一旦Drone服务已启动并运行,可以安装runners来执行构建流水线(pipeline).

Drone runners 轮询服务器以查找要执行的工作任务,这里提供了几种不同的runners针对不同用户场景和运行时环境进行了优化,可以根据情况安装一个或多个,一种或多种。

代码语言:shell复制
1、Docker Runner
2、kubernetes Runner
3、Exec Runner
4、SSH Runner
5、Digital Ocean Runner
6、Macstadium Runner

Docker runner 是一个守护进程,它在一个短生命周期容器中执行流水线(pipeline)任务。可以安装一个单独的 Docker runner,或者在多台机器上安装来创建一个构建集群。

Docker runner 是一个通用的 runner,针对可以在无状态容器中运行测试和编译代码的项目进行了优化。

Docker runner 不太适合不能在容器内运行测试或编译代码的项目,包括以 Docker 不支持的操作系统或体系结构为目标的项目,如macOS

启动 Drone Server 和 Drone Runnner

安装的配置文件如下(docker-compose-drone.yaml):

代码语言:yaml复制
version: "3.8"

services:
  drone:
    image: drone/drone:2.0.0 #不要用latest,latest并非稳定版本
    ports:
      - "7000:80"
    networks:
      - "drone"
    volumes:
      - /data/drone/:/var/lib/drone/:rw
      - /var/run/docker.sock:/var/run/docker.sock:rw
    environment:
      #- "DB_PASSWD_FILE=/run/secrets/db_passwd"
      - DRONE_DEBUG=true
      - DRONE_DATABASE_DATASOURCE=drone:123456@tcp(localhost:3306)/drone?parseTime=true #mysql配置,要与上边mysql容器中的配置一致
      - DRONE_DATABASE_DRIVER=mysql
      - DRONE_GITEA_SKIP_VERIFY=false
      - DRONE_GITEA_CLIENT_ID=xxxxxx
      - DRONE_GITEA_CLIENT_SECRET=xxxxxx
      - DRONE_GITEA_SERVER=http://localhost:3000/
      - DRONE_TLS_AUTOCERT=false
      - DRONE_RUNNER_CAPACITY=2
      - DRONE_RPC_SECRET=48f11fe546a25099cde4a05ce35a4815 #RPC秘钥
      - DRONE_SERVER_PROTO=http #这个配置决定了你激活时仓库中的webhook地址的proto
      - DRONE_SERVER_HOST=localhost:7000
      - DRONE_USER_CREATE=username:root,admin:true #管理员账号,是你想要作为管理员的Gitea用户名
      - DRONE_USER_FILTER=root
      - DRONE_DATADOG_ENABLE=false
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
  drone-runner:
    image: drone/drone-runner-docker:1.6.3
    networks:
      - "drone"
    depends_on:
      - drone
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:rw
    environment:
      - DRONE_RPC_HOST=localhost:7000
      - DRONE_RPC_SECRET=48f11fe546a25099cde4a05ce35a4815
      - DRONE_RPC_PROTO=http
      - DRONE_RUNNER_CAPACITY=4
      - DRONE_RUNNER_NAME=runner
      - DRONE_RUNNER_LABELS=machine1:runner1
      - DRONE_DEBUG=true
      - DRONE_LOGS_DEBUG=true
      - DRONE_LOGS_PRETTY=true
      - DRONE_LOGS_NOCOLOR=false
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
networks:
  drone:
    external: true
    name: traefik_default

如果是使用docker-compose方式启动,只需要在docker-compose-drone.yaml的目录下输入docker-compose up -d 即可

本次通过以下命令可以启动Drone服务,容器通过环境变量配置,如果想要查看完整的配置参数,请查看配置参考(https://docs.drone.io/server/reference)

代码语言:shell复制
docker stack deploy -c docker-compose-drone.yaml drone

以上设置中 Server 的端口号为 7000,因此本地环境浏览器进入localhost:7000即可访问管理页面,建议配置域名和 Nginx 或 Caddy 反向代理访问。本次使用的代理组件是traefik代理,更多关于traefik的使用说明请参考traefik使用说明

Drone 的登录账号默认是绑定 Gitea 账号的,因此只要登录了 Gitea,Drone 也会自动登录。

在打开并登录 Drone 后,你的 Repositories 应该是空的,因为没有同步 Gitea 的代码仓库到 Drone CI 里,只要在首页里的右上角点击SYNC按钮,Drone 便会自动开始同步 Gitea 的代码仓库。同步完成后需要激活仓库,配置完成后,会自动到对应的私有仓库中创建Webhook构建钩子。

如果 Steps 需要挂载宿主机的文件夹,需要在 Drone 对应项目中的 SETTINGS 里的 Project settings 里需要勾选Trusted,这意味着开启容器的特权模式去挂载宿主机的文件夹。开启这个设置用户的权限必须是 admin ,其他用户没有权限开启。

Drone CI 自动部署的实例

在项目代码的根目录新建一个.drone.yml文件,一旦代码上传到代码仓库( github, gitlab, gitea 等),git 仓库会通过 Drone 预先埋好的 Webhoot 钩子发送事件请求给 Drone,Drone 接收到事件请求后会找到仓库项目根目录中的.drone.yml文件进行解析并根据文件的描述执行任务。

Drone CI 构建的每个 step 都会根据镜像产生一个 Docker 容器,并在容器里运行指定任务。

首先每个 Pipline 都有的头描述部分:

代码语言:shell复制
kind: pipeline # Pipeline 的类型,其他的还有 secret and signature。
type: docker # 定义了执行任务的类型,这里会使用 Docker 执行。
name: web # 定义 Pipline 的名字,一个 .drone.yml 可以有多个不同名字的 Pipeline。

然后是描述任务的每个步骤,steps 属性后描述此步骤的 name (名字) 和 image (镜像),每一步都会用到一个镜像,任务进行时会根据提供的镜像名字拉取镜像并生成一个临时 Docker 容器运行任务指令,步骤完成后自动删除。

代码语言:shell复制
steps:
- name: build-imaeg # 步骤名
  image: docker # 步骤需要用到的镜像

下面是一个 vue 前端程序打包成 Docker 镜像并部署到服务器的例子。文中介绍的范例主要想覆盖常见的坑,对于新手可能会比较复杂,如果看不懂,没关系,可以直接跳过这一节,自己尝试动手安装 Drone CI 后回头再细品。

.drone.yml 文件

代码语言:yaml复制
kind: pipeline
type: docker #在docker runner中运行
name: web

#定义setups,每个setup有属于自己的name,最后会显示在Drone CI管理页面的侧边栏
steps:
- name: restore-cache # 把之前缓存好的数据取出
  image: drillster/drone-volume-cache
  settings:
    restore: true
    mount: # 缓存挂载的文件夹
      - ./.npm-cache
      - ./node_modules
  volumes:
    - name: cache
      path: /cache

- name: compile #编译
  image: node:12
  commands:
  - yarn config set registry https://registry.npm.taobao.org -g
  - yarn config set cache ./.npm-cache --global
  - yarn install
  - yarn run build

- name: build image #打成docker镜像
  image: docker
  failure: ignore
  volumes:
  - name: sock
    path: /var/run/docker.sock
  commands:
  - docker build -t localhost:v1.0 -f Dockerfile .
  - docker image prune -f --filter "dangling=true"   # 清理无用镜像

- name: rebuild-cache # 把依赖和 npm 缓存放到缓存里
  image: drillster/drone-volume-cache
  settings:
    rebuild: true
    mount:
      - ./.npm-cache
      - ./node_modules
  volumes:
    - name: cache
      path: /cache

- name: deploy #部署到服务器上
  image: docker
  failure: ignore
  volumes:
  - name: sock
    path: /var/run/docker.sock
  commands:
  - docker service ls|grep test || export SERVICE=down #先检查服务是否存在,存在更新,不存在创建
  - |
    if [ "$SERVICE" != "down" ]
    then
      docker service update --image test:v1.0 test_test
    else
      docker stack deploy -c deploy.yaml autocd-web
    fi            
  # 循环检测服务是否启动成功
  - |
    while true
    do
      docker service ps test_test|awk '{print $6}'|awk 'NR==2'|grep 'Running' || export SERVICE=down
      if [ "$SERVICE" == "down" ]
      then
          echo -e "33[5;35;40m 正在启动中请稍后 ... 33[0m"
          export SERVICE=up
          continue
      else
          docker service logs -n 200 test_test
          sleep 3
          break
      fi
    done          

# 挂载宿主机文件到docker容器中      
volumes:
- name: sock
  host:
    path: /var/run/docker.sock
- name: cache
  host:
    path: /tmp/cache
  
# 创建触发器,绑定分支及事件及上一次成功时才运行
trigger:
  branch:
    - master
  event:
    - pull_request
    - push
  status:
    - success
    - failure

node:
  machine1:runner1

Dockerfile 文件

代码语言:shell复制
# 设置基础镜像,如果本地没有该镜像,会从Docker.io服务器pull镜像
# 这里会直接调用宿主机的密钥登录私有仓库。
FROM nginx:1.19.2-alpine

# 编译项目,使用npm安装程序的所有依赖,利用taobao的npm安装,并打包编译成静态文件
# 这两步在drone里已经完成
# 复制所有静态文件到 /usr/share/nginx/html下。
# 拷贝配置文件到nginx配置目录中
COPY dist/ /usr/share/nginx/html/
ADD nginx.conf /etc/nginx/nginx.conf
ADD default.conf /etc/nginx/conf.d/default.conf


# 暴露container的端口
EXPOSE 80

# 运行命令
CMD ["nginx", "-g", "daemon off;"]

流水线说明

上面的范例有5个Steps

  • restore-cache
  • compile
  • build image
  • rebuild-cache
  • deploy

简单整理一下每一步(详细的上面注释都有解释)

1、clone克隆私有仓库代码(默认自动添加);

2、restore-cache 步骤会把之前缓存的文件从宿主机中取出;

3、compile 步骤时 yarn或npm 跳过已经安装过的依赖;

4、build 步骤会时根据仓库中的 dockerfile 打成本地镜像包,由于不需要推送到docker私有镜像仓库即并没有使用plugins/docker插件;

5、rebuild-cache 步骤把缓存通过挂载文件放到宿主机中;

6、deploy 步骤使用 将应用部署到容器中;

优化

因为一次构建每一个 steps 都会新生成一个容器并在容器里运行构建,沙盒环境里没有缓存数据。通过restore-cache和rebuild-cache这两个 steps 建立宿主机与容器的缓存,把 vue 的依赖 node_modules 目录和 yran 缓存通过 volumes 映射到宿主机上,在下一次构建并安装依赖时 yarn 会自动跳过没有变化的依赖包,从而加快构建速度。

实际在构建过程中,Drone CI会默认在所有setup最前面添加一个克隆代码的setup(clone), 使用自建的 Gitea 服务内网拉取可以极致地加快构建速度,等代码克隆完成后才会开始执行预定义的一些setup,如果中途报错,即会直接报错退出整个pipeline流水线流程。

多节点运行

在 docker-compose-drone.yaml 文件中定义 Runner 的DRONE_RUNNER_LABELS环境变量可以为 Runner 加上标签,在定义 .drone.yml 时通过这个标签让 pipeline 路由到不同的 Runner 执行任务。

例如我有两个不同的机器放在不同的地方,在这两台机器上运行 Runner 并使用DRONE_RUNNER_LABELS环境变量分别定义这两个 Runner 的标签,例如在第一个 Runner 里DRONE_RUNNER_LABELS=nodeA:runnerA,另一个 Runner 里DRONE_RUNNER_LABELS=nodeB:runnerB,那么在.drone.yml文件中我们可以定义

代码语言:yaml复制
kind: pipeline
type: docker
name: default

steps:
- name: build
  image: golang
  commands:
  - go build
  - go test

node:
  nodeA: runnerA

那么这个任务就只会在标签是nodeA:runnerA的 Runner 里运行。

如果想要在两个节点中运行,可以把这两个标签都加上,例如:

代码语言:yaml复制
node:
  nodeA: runnerA
  nodeB: runnerB

因为 Runner 会主动心跳连接 Server 并在 Server 上注册自己,不需要固定的网络地址而且足够轻量, 因此这个 Runner 节点可以是你的 PC 机、笔记本,甚至是树莓派。

0 人点赞