Drone 是一个基于Docker容器技术的可扩展的持续集成引擎,由GO语言编写,可用于自动化测试与构建,甚至发布。每个构建都在一个临时的Docker容器中执行,使开发人员能够完全控制其构建环境并保证隔。相对于常见的Jenkins,选中 Drone的原因在于它非常简洁,不像Jenkins那样复杂,同时它拥有可以满足基本需求的能力,并且提供了许多实用的插件,如GitHub
,Email
,微信
,钉钉
等。
Drone 官方地址:https://www.drone.io/
Drone 开源地址:https://github.com/harness/drone
由于本人是在公司内部服务器部署的,所以都是使用的HTTP部署。HTTPS部署详见另一位大佬的文章:https://www.cnblogs.com/yan7/p/15881087.html
Drone 版本 2.9.1
Gitea 版本 1.17.6
Docker 版本 20.10.12
Harbor 版本 1.10.10
仓库项目 .NET5
Drone官方文档 中支持的Git仓库有很多种:
本文示例也选用相对Gitlab
更轻量化的Gitea
,演示Gitea版本为:1.17.6,Gitea
部署不是本文重点,请移步其他文章。
登录Gitea后,点击右上角头像选择设置(如果没设置选项,需要管理员权限):
然后选择 应用,在最下面创建OAuth2应用,填写名称和重定向URI:
点击创建后,会跳转到这个页面,记住 客户端ID和 客户端密钥,后面部署Drone会用到,客户端密钥在退出本页面时候就会显示为*,所以尤其需要记住 客户端密钥,然后点击保存。
Drone
数据存储默认使用 sqlite
数据库。并且提供支持 postgres
和 MySql
官方文档中强烈建议使用 postgres
而非 mysql
。 某些操作在 mysql
未得到优化。 https://docs.drone.io/server/storage/database/
PS: 支持 postgres9.6 及更高版本 、 mysql:5.6 及更高版本
DockerCompose.yml:
# 在执行DockerCompose前,需要创建网络 docker network create drone version: '3.9' # 创建自定义网络 networks: drone: name: drone driver: bridge services: # Drone的数据库服务 db: # 拉取的镜像名称和版本号 image: postgres:latest # 容器名称 container_name: drone_db # 该容器随Docker启动而启动 restart: always # 加入到drone网络 networks: - drone # 端口映射,左边宿主机端口:右边容器内部端口 ports: - '7931:5432' environment: - POSTGRES_USER=drone # PGSQL默认用户 - POSTGRES_PASSWORD=drone # PGSQL默认密码 - POSTGRES_DB=drone # PGSQL默认数据库 volumes: # 数据持久性挂载宿主机 左边宿主机路径:右边容器内路径 - /volumes/drone/db:/var/lib/postgresql/data # Drone Server 服务 server: image: drone/drone:2.9.1 # 目前drone最新版本为 2.9.1 container_name: drone_server # 该容器随Docker启动而启动 restart: always # 加入到drone网络 networks: - drone # 端口映射,左边宿主机端口:右边容器内部端口 ports: - '7929:80' environment: - DRONE_SERVER_PROTO=http # 访问协议,创建webHooks和重定向 - DRONE_SERVER_HOST=192.168.2.7:7929 # 主机名称,创建webHooks和重定向 # 与 drone runner 通讯的密钥 可以在 服务器(Linux) 中使用 openssl 生成密钥 - DRONE_RPC_SECRET=e1ad8a7f3dbc68ca9c21bcc949335009 # 设置管理员账户,username和Gitea账户名称需要一致 - DRONE_USER_CREATE=username:young,admin:true - DRONE_DATABASE_DRIVER=postgres # 数据库类型 - DRONE_DATABASE_DATASOURCE=postgres://drone:drone@db/drone?sslmode=disable # 数据库连接 - DRONE_GIT_ALWAYS_AUTH=true # 使用 oauth 身份验证信息拉取代码 - DRONE_GITEA_SERVER=http://192.168.2.7:3000 # gitea服务器地址 - DRONE_GITEA_CLIENT_ID=2c921d85-e40e-41f8-90e0-c77c383786b5 # gitea 客户端 id 刚才创建的OAuth2的客户端Id - DRONE_GITEA_CLIENT_SECRET=ZVZoRWK6jR5mqgAIm6sB5VX6C2LPK1sYKv4hQWyTdULu # gitea 客户端 密钥 刚才创建的OAuth2的客户端密钥 - DRONE_GITEA_SKIP_VERIFY=false # 禁用 gitea 链接时 tls 验证 volumes: # 数据持久性挂载宿主机 左边宿主机路径:右边容器内路径 - /volumes/drone/server:/data - /var/run/docker.sock:/var/run/docker.sock # 依赖的容器 depends_on: - db # Drone Docker Runner runner: image: drone/drone-runner-docker:1.8.0 # 目前drone-runner-docker最新版本为 1.8.0 container_name: drone_runner restart: always networks: - drone # 加入到drone网络 ports: - '7930:3000' environment: # 名称 - DRONE_RUNNER_NAME=docker-runner - DRONE_RUNNER_CAPACITY=10 # 限制runner可执行的并发管道数量 默认为2 - DRONE_RPC_PROTO=http # 访问drone server 协议 - DRONE_RPC_HOST=server # 访问drone server 服务器地址 # 与 drone server 通讯的密钥, 需与上面Server的 DRONE_RPC_SECRET 值相同 - DRONE_RPC_SECRET=e1ad8a7f3dbc68ca9c21bcc949335009 - DRONE_UI_USERNAME=admin # Drone Runner 的 UI 用户账号 - DRONE_UI_PASSWORD=qwe123 # Drone Runner 的 UI 用户密码 volumes: - '/var/run/docker.sock:/var/run/docker.sock' depends_on: - server
将上述保存,文件名为:drone-docker-compose.yml
docker-compose 执行命令:
docker-compose -f drone-docker-compose.yml up -d # -f dockerfile文件名,不使用-f参数时,默认就为 docker-compose.yml # -d 后台启动并运行容器
如果未报错,那么docker就启动成功了,使用Portainer查看容器状态:
显示都为running状态。
部署成功后,访问7929端口的页面:
点击Continue会自动跳转到Gitea的授权页面:
如果你浏览器没有登陆Gitea,会先让你登陆:
登陆且授权后,就会跳转到Drone的页面了,只需要授权一次即可,往后我们登录了Gitea就直接进入Drone了。
进入Drone会看到未激活的仓库,选择需要激活的仓库,然后我们点击激活它:
激活成功后,回到Gitea查看被激活的仓库,就会看到仓库已经自动的配置好了WebHook(Web钩子):
点击钩子,进去找到测试推送,点击测试推送,如果出现如下绿色,那钩子就没问题了:
踩坑小Tips:
如果是红色,且HTTP相应内容包含
context deadline exceeded (Client.Timeout exceeded while awaiting headers)
,请检查你的仓库根目录是否存在Drone的.drone.yml
配置文件,我就是这个配置文件放错了地方卡了我大半天。。。
到这里我们的Drone就安装完毕了,激活仓库后,我们向仓库推送一个commit,Gitea就会发送消息通知Drone去自动构建了!
Drone支持不同环境的不同管道配置,这里我使用Docker Pipelines管道配置简单来说就是Drone的每一步操作都在一个临时的Drone的容器中进行,容器操作完会自动销毁,容器之间会共享当前的工作目录。
本人这里使用了私有镜像仓库 Harbor
,Harbor
的搭建文章点击此处。
Drone 配置文件 .drone.yml
如下:
kind: pipeline # 默认为 pipeline type: docker name: deployment # 构建文件名称 steps: # 数组结构,流水线化的构建步骤 # 步骤1 构建 - name: build # 因为drone支持同时书写多个构建任务,所以需要为本任务起个名字 pull: if-not-exists # 如果镜像不存在则拉取,免去每次都要重新下载 image: mcr.microsoft.com/dotnet/sdk:5.0 # 本步骤运行在哪个docker镜像中,该镜像必须存在于 docker hub 中,可在 https://hub.docker.com/_/microsoft-dotnet-sdk 查看对应版本号 commands: # 构建过程中,将会依次执行的命令,如果命令退出码非0,将会终止构建本次构建 - dotnet restore # 项目重建 - dotnet build -c Release # 项目生成构建 - echo ========项目生成成功======== # 输出 # 步骤2 将镜像推送到 Harbor - name: publish 2 harbor pull: if-not-exists # 如果镜像不存在则拉取,免去每次都要重新下载 image: plugins/docker settings: dockerfile: Demo/Dockerfile # Dockerfile 在项目中的位置 tags: latest # 生成镜像后的Tag标签 insecure: true # 是否不安全 registry: 192.168.2.7:8088 # 私有镜像仓库地址 repo: 192.168.2.7:8088/zhjs/drone-ci-demo # 仓库地址/Harbor项目名称/自定义镜像名称 username: # 从drone仓库配置中秘密空间读取用户名 from_secret: docker_username password: # 从drone仓库配置中秘密空间读取密码 from_secret: docker_password # 步骤3 使用ssh访问主机,拉去镜像并运行部署 - name: deploy pull: if-not-exists # 如果镜像不存在则拉取,免去每次都要重新下载 image: appleboy/drone-ssh settings: # 需要部署的主机地址 host: 192.168.2.7 # 主机ssh端口 port: 22 # 主机登陆用户名 username: root password: # 从drone仓库配置中秘密空间读取密码 from_secret: ssh_pwd script: - echo =========暂停并删除旧容器======== - docker stop drone-ci-demo-1 && docker rm drone-ci-demo-1 - docker stop drone-ci-demo-2 && docker rm drone-ci-demo-2 - echo =========删除旧镜像============= - docker rmi 192.168.2.7:8088/zhjs/drone-ci-demo:latest - echo ========从harbor拉取最新镜像======== - docker pull 192.168.2.7:8088/zhjs/drone-ci-demo:latest - echo ===============运行镜像========== - docker run --name drone-ci-demo-1 -p 5555:80 -d 192.168.2.7:8088/zhjs/drone-ci-demo:latest - docker run --name drone-ci-demo-2 -p 5556:80 -d 192.168.2.7:8088/zhjs/drone-ci-demo:latest - echo ========部署成功======== # 步骤4 部署完成,邮件通知 - name: notify pull: if-not-exists # 如果镜像不存在则拉取,免去每次都要重新下载 image: drillster/drone-email settings: recipients_only: true # 只发送给指定邮件收件人,不默认发送给流水线创建人 host: smtp.qq.com #SMTP服务器 例如 smtp.qq.com port: 465 #SMTP服务端口 例如QQ邮箱端口465 subject: "Drone Build Complete!" # 邮件主题内容 username: #邮箱用户名 from_secret: qqmail_username password: #邮箱密码 from_secret: qqmail_pwd from: from_secret: qqmail_username recipients: #收件人 from_secret: email_recipients # 格式:xxxx,xxxx when: #执行条件 status: - success - changed - failure
文件编写完成后,把代码git push
到仓库中,Gitea会通知Drone进行部署,Drone找到.drone.yml
配置文件,就会按照配置文件中的步骤进行构建了,部署期间可以在Drone中查看到每一步的部署情况
首次部署的速度可能略慢,最终部署成功图:
总结:对于小团队来说,总体是完全可以接受的,自动部署一旦配置好了,所有的编译/测试/打包/部署的工作就交给Drone去完成了,而我们只需要专注于我们的代码编写就行了!