上一次我们使用
还需要一个自动构建工具来解放生产力,这里我推荐使用
为什么选用
相对来说主流的
废话少说,直接开搞~
这里我的服务器环境使用的是最新的
1 安装 Gitea
Gitea
2 安装 Drone
新版的
2.1 Gitea 创建 OAuth2 应用程序
我们进入
来创建一个
这里的重定向
创建成功后就可以拿到客户端
2.2 创建共享密钥
这里我们还需要创建一个共享密钥来供
我们可以使用
$ openssl rand -hex 16
da7fb75c68106b563100bec5ce166b72
2.3 安装 Docker Compose
这里我使用
Docker Compose
安装过程可参考:https://www.runoob.com/docker/docker-compose.html
2.4 编写 docker-compose.yml 文件
这里我们通过使用 Docker Compose 来构建并启动 Drone
$ mkdir drone $ cd drone $ vim docker-compose.yml
在配置文件中,我们设置 docker-compose.yml 的格式为 3 号版本,定义以下两个
- Drone Server:使用
drone/drone:1
版本镜像,将 drone 容器的 80 端口映射到宿主机的 7079 端口。映射容器内 /data
目录到宿主机的/data/drone
目录,以便 drone 可以保留数据。配置服务自动重新启动,并配置构建 drone 所需的环境变量。 - Docker Runner:使用
drone/drone-runner-docker:1
版本镜像,将 docker 启动句柄挂载到容器/var/run/docker.sock
文件中,以便 drone 可以使用 docker-runner 来执行镜像构建任务。环境变量中需要配置 drone server 的端口协议以及共享密钥,以便与 server 进行通信。
具体配置可参考如下配置:
version: '3'
services:
# 容器名称
fan-drone-server:
# 构建所使用的镜像
image: drone/drone:1
# 映射容器内 80 端口到宿主机的 7079 端口
ports:
- 7079:80
# 映射容器内 /data 目录到宿主机的 /data/drone 目录
volumes:
- /data/drone:/data
# 容器随 docker 自动启动
restart: always
environment:
# Gitea 服务器地址
- DRONE_GITEA_SERVER=https://git.ffis.me
# Gitea OAuth2 客户端 ID
- DRONE_GITEA_CLIENT_ID=aaaaaaaaaaa-8888-8888-8888-fffffffffffff
# Gitea OAuth2 客户端密钥
- DRONE_GITEA_CLIENT_SECRET=aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbffffffff
# drone 的共享密钥
- DRONE_RPC_SECRET=asdfsadfasdfsadfsadfasdf
# drone 的主机名
- DRONE_SERVER_HOST=drone.ffis.me
# 外部协议方案
- DRONE_SERVER_PROTO=https
# 创建管理员账户,这里对应为 gitea 的用户名
- DRONE_USER_CREATE=username:noisky,admin:true
fan-docker-runner:
image: drone/drone-runner-docker:1
ports:
- 7080:3000
restart: always
depends_on:
- fan-drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# 用于连接到 Drone 服务器的协议。该值必须是 http 或 https。
- DRONE_RPC_PROTO=https
# 用于连接到 Drone 服务器的主机名
- DRONE_RPC_HOST=drone.ffis.me
# Drone 服务器进行身份验证的共享密钥,和上面设置一样
- DRONE_RPC_SECRET=asdfsadfasdfsadfsadfasdf
# 限制运行程序可以执行的并发管道数。运行程序默认情况下执行 2 个并发管道。
- DRONE_RUNNER_CAPACITY=2
# docker runner 名称
- DRONE_RUNNER_NAME=fan-docker-runner-1
2.5 构建 drone 和 runner
docker-compose up -d
-d 为后台运行
这里我的
贴出我的
location / {
proxy_pass http://127.0.0.1:7079/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
2.6 打开 drone
到这里如果没有出问题的话
这里我们进行授权后就跳转到
进入
激活后回到
我们可以进去测试钩子,一般是没问题的
到这里我们的
3 配置 Drone 自动构建
drone
简单来说就是
这里我还是构建一个
3.1 本地部署
本地部署主要步骤:
- drone
拉取最新的代码到当前工作目录 - drone
创建 maven/grade 容器,通过指定的构建工具 maven/grade 等将代码编译 / 打包为 jar 包,然后将 jar 包和 Dockerfile 文件复制到挂载的宿主机共享目录中 - drone
创建 ssh 容器,在容器中通过 ssh 连接到宿主机,通过定义好的命令,到 jar 和 Dockerfile 目录中将 jar 包制作构建为镜像,然后通过镜像创建应用容器并运行,期间会删除之前老的应用程序容器和镜像 - drone
创建钉钉通知容器,将构建成功 / 失败的消息通过钉钉机器人通知到管理员
至此本地构建完毕,这个构建步骤是我自己搞的,其优点是所有操作都在本机执行,构建的应用不用经过网络传输,整体部署的速度很快,其缺点是只能单机部署,无法进行分布式多机器部署,如果自己个人单机使用的话推荐使用这种方式,我的测试
编写
在仓库的根目录下创建.drone.yml
配置文件参考如下配置:
# drone 本地构建
kind: pipeline
type: docker
name: MyHelloWorld
# drone 构建步骤
steps:
# 1.maven 打包
- name: maven compile
pull: if-not-exists
image: maven:ibmjava-alpine
volumes:
# maven 构建缓存
- name: cache
path: /root/.m2
# 挂载宿主机的目录
- name: data
path: /home
commands:
# 开始打包 maven 工程
- cd demo
- mvn clean package -Dmaven.test.skip=true
# 将打包后的文件复制到宿主机映射目录
- cp target/*.jar /home
- cp ../Dockerfile /home
# 2. 使用 ssh 访问主机制作镜像并运行
- name: ssh commands
pull: if-not-exists
image: appleboy/drone-ssh:1.5.7
settings:
host: 0.0.0.0
username: root
password:
# 从 drone 仓库配置中秘密空间读取密码
from_secret: ssh_password
port: 22
script:
- echo ======= 暂停容器 =======
- docker stop `docker ps -a | grep springdemo | awk '{print $1}' `
- echo ======= 暂停旧容器和镜像 =======
- docker rm -f `docker ps -a | grep springdemo | awk '{print $1}' `
- docker rmi `docker images | grep springdemo | awk '{print $3}' `
- echo ======= 开始构建新镜像 =======
- cd /data/drone/helloDemo
- docker build -t springdemo:v1 .
- echo ======= 开始部署应用 =======
- docker run -d -p 8188:8180 --name springdemo springdemo:v1
- echo ======= 清理构建文件 =======
- rm -rf *
- echo ======= 部署成功 =======
# 3. 钉钉通知
- name: dingTalk notification
pull: if-not-exists
image: guoxudongdocker/drone-dingtalk:latest
settings:
token:
from_secret: dingtalk_token
type: markdown
message_color: true
message_pic: true
sha_link: true
when:
status: [failure, success]
# 挂载的主机卷,可以映射到 docker 容器中
volumes:
# maven 构建缓存
- name: cache
host:
# path: /tmp/cache/.m2
path: /var/lib/cache
# maven 构建后与宿主机通信的共享目录
- name: data
host:
path: /data/drone/helloDemo
# drone 执行触发器
trigger:
branch:
- master
文件编写完成后,git push.drone.yml
3.2 分布式云部署
云部署主要步骤:
- drone
拉取最新的代码到当前工作目录 - drone
创建 maven/grade 容器,通过指定的构建工具 maven/grade 等将代码编译 / 打包为 jar 包,然后将打包完成后的 jar 移动到根目录,也就是工作目录 - drone
创建 docker 构建容器,将 jar 通过 dockerfile 指定的方式构建为镜像,然后将构建完成的镜像上传到腾讯云 / 阿里云私有仓库中 - drone
创建 ssh 容器,通过 ssh 连接到一个或多个主机,然后批量从私有仓库中拉取最新镜像进行部署 - drone
创建钉钉通知容器,将构建成功 / 失败的消息通过钉钉机器人通知到管理员
这种方式配置较为简单,所有操作都在
不过好在同一服务商的私有仓库都是通过内网进行访问的,访问速度影响可忽略不计;
而且有很大的优化空间,毕竟我们写的代码只有几百
所以可以通过对
这样每次更新的就只有我们写的代码,传输的数据量就很少了,不过这个属于比较高级的应用了,我们这里先不研究了;
云部署主要好处是可以做到分布式部署,多个主机可以从私有仓库中拉取最新镜像,实用性还是很高的。
编写
同样也是在仓库的根目录下创建.drone.yml
参考如下配置:
# drone 云部署
kind: pipeline
type: docker
name: MyHelloWorld
# drone 构建步骤
steps:
# 1.maven 打包
- name: maven compile
pull: if-not-exists
image: maven:ibmjava-alpine
volumes:
# maven 构建缓存
- name: cache
path: /root/.m2
commands:
# 开始打包 maven 工程
- cd demo
- mvn clean package -Dmaven.test.skip=true
# 将打包后的 jar 包移动到 Dockerfile 文件同级目录
- mv target/demo-0.0.1-SNAPSHOT.jar ../demo-0.0.1-SNAPSHOT.jar
# 2.Docker 制作镜像,推送到私有仓库
- name: docker build
image: plugins/docker
pull: if-not-exists
volumes:
- name: docker
path: /var/run/docker.sock
settings:
username: username
password:
from_secret: dockerHub_password
tags:
- latest
repo: ccr.ccs.tencentyun.com/fanfan/hellodemo
registry: ccr.ccs.tencentyun.com
dockerfile: Dockerfile
# 3. 使用 ssh 访问主机运行最新版容器
- name: ssh commands
pull: if-not-exists
image: appleboy/drone-ssh:1.5.7
settings:
host: 49.234.106.44
username: root
password:
from_secret: ssh_password
port: 22
script:
- echo ======= 暂停容器 =======
- docker stop `docker ps -a | grep springdemo | awk '{print $1}' `
- echo ======= 暂停旧容器 =======
- docker rm -f `docker ps -a | grep springdemo | awk '{print $1}' `
- echo ======= 开始部署应用 =======
- docker run -d -p 8188:8180 --name springdemo --restart=always ccr.ccs.tencentyun.com/fanfan/hellodemo:latest
- echo ======= 部署成功 =======
# 4. 钉钉通知
- name: dingTalk notification
pull: if-not-exists
image: guoxudongdocker/drone-dingtalk:latest
settings:
token:
from_secret: dingtalk_token
type: markdown
message_color: true
message_pic: true
sha_link: true
when:
status: [failure, success]
# 挂载的主机卷,可以映射到 docker 容器中
volumes:
# maven 构建缓存
- name: cache
host:
# path: /tmp/cache/.m2
path: /var/lib/cache
- name: docker
host:
path: /var/run/docker.sock
# drone 执行触发器
trigger:
branch:
- master
编写好部署的配置文件,推送到仓库中,drone
首次部署的速度可能略慢,我这里用了
部署成功后的钉钉通知页面
4 资源占用
Gitea
可以看到总占用也不到
自动部署一旦配置好了,所有的编译
膜拜大佬,请教下大佬,drone 在 kubernetes 的 CD 操作你是如何实现的?插件需要自己做吗?
請問能知道我這個為什麼所有的 build 都是在 pending 嗎?
version: '3'
services:
gitea:
drone-server:
drone-runner:
请问为什么使用 exec runner 执行的时候无法进入宿主机目录呢,一直在临时目录下,但是宿主机的所有命令是可以用的,但是如果我想在宿主机的 home 目录下创建文件是不可以的
可以考虑使用 SSH 连接到宿主机操作 ...
也就是说,它的这个操作全部都是在临时目录下进行的吗,用完就删除啊,就和 travisci 差不多那种了吗,它的这个本地执行真的让我以为可以直接操作宿主机 ......
不知道你的 exec runner 是什么情况,我用的是 docker runner 每一个步骤都在一个 docker 容器中,操作的文件是共享的,也可以和宿主机进行共享,但是直接操作宿主机我是通过 ssh 容器再连接到宿主机的,直接操作宿主机好像要配置 docker 的权限什么的,也可以做 但是较为麻烦所以就没去研究 
我看了 drone 的官方文档,上面说 exec runner 有一个工作区,工作区在一个临时目录里面,linux 的 tmp 目录,我用 pwd 查看了,执行完构建就会消失,而且我在构建的过程中使用 linux 命令是无法切换到宿主机的,比如 cd,但是可以在创建的临时目录里面操作,但是可以使用我宿主机里面配置的环境变量,所以我使用 exec runner 就很疑惑,我可以使用宿主机的任何东西,但是无法和宿主机直接交互,但是这个 exec runner 官方说的是没有隔离的,我在想我是不是哪里没有配置,比如把这个临时目录映射到宿主机?
你好,刚用 drone,请教个问题,使用 gitea / drone 来管理代码和 cicd,当前对于公共仓库是没有问题的,可是如果设置仓库为私有时,就出现问题了,查阅了官方文档,提到两个参数:DRONE_GIT_USERNAME / DRONE_GIT_PASSWORD,然后也设置了,可是还是无法正常构建和部署,麻烦指导一下,谢谢了
问下 我 .drone.yml 里有这么一段脚本 secret 已经从 drone 的 secrets 添加进去了 但是我看运行时打印的 ALIYUN_OSS_BUCKET 变量 * 号或者我在 drone 的 secrets 添加的变量, 是哪里出错了
并没有打印出
deployment-to-oss:
你好,请问为什么我的部署的第一个步骤的 clone 时间都要花费几十秒甚至分钟级别呢,我看你的截图里基本是 1s 内
比如你这张图中的第一个步骤

项目代码在 KB 级别,非常小
这个不太好定位问题,你自己在机器上手动 clone 一下试试要多久,如果很慢的话就考虑是 git 服务的速度是不是不太稳定
大佬,请问怎么使用 drone-docker-runner 拉取私有镜像啊。
我的主机连不上互联网,所以需要的镜像都是从外部导入进去的,但是 drone 似乎每次都会重新 pull 镜像,即使我配置了 pull: if-not-exists 也不行。
明明我本地 docker 拥有镜像 A,.drone.yml 中也只声明了一个步骤,在镜像 A 中执行 hello world
但 drone 构建时老是报错:
default: Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:38996->[::1]:53: read: connection refused
default – clone: Error
使用局域网的镜像源,配置了 image_pull_secrets 也不行。
如果只需要在本地主机部署的话,可以放弃容器化流水线的思想,drone-docker-runner 里只用一个 ssh 的镜像,远程连接到主机模拟用户操作就行了
哇,昨晚弄那么晚,今天在互联网环境起了一个 docker-runner,发现他在拉取流水线里面需要的镜像之前拉取了 drone/git 这个镜像,我把这个镜像放到内网中去后就 OK 了。
真的坑,日志里看不出缺少什么镜像,只看到我配置的那几个 registry-mirrors 拉取失败的消息,也没看到从 insecure-reistries 拉取的消息,误导我老半天了。
楼主,目前 springboot 单模块应用用这个 drone 跑起来是没问题的,但是我们目前的项目,是有多个 module 的,每个 module 就是一个服务,.drone.xml 只能放在根目录,对于这种多模块的项目,你们这边有什么好的方案,谢谢 
如果多模块同时部署的话,使用 push 事件触发 drone 构建后,可以在编译阶段进入不同的目录依次进行编译打包(如果是主从工程,直接在主工程统一编译打包),然后分别将打包后的 jar 包发布,在运行部署阶段再统一的部署打包好的服务即可,因为在配置文件里面是很灵活的,具体打包哪一个服务,打包后文件的位置怎么存放,都是可以分别操作的; 和其他自动构建工具主要的区别就是 drone 是容器化思想,将每一个步骤都在一个容易里面运行,如果统一使用 docker hub 中心部署的方式很方便,如果不适用 docker 中心仓库部署的话,则需要通过自己处理下容器间具体怎么通信
docker
我们业务上因为经常要把整套系统移植出去,不适合用镜像仓库,直接一整套在同一套机器的;按你刚才说的,一更新就全部应用都更新了,有时我们只需要更新部分应用而已,这个要怎么搞呢
.drone.yml 可以写成按照不同分支触发不同的构建条件,可以给需要单独构建的应用写一个分支触发构建
https://docs.drone.io/promote/
谢谢,后面我自己试下;还有个问题,在 step 之前我定义的 environment 里面的参数,类似这个
kind: pipeline
type: docker
name: apiservice
environment:
dronePRENAME: oemsys
APPNAME: apiservice
steps: 打包
# 1.maven
name: maven compile 构建缓存
pull: if-not-exists
image: maven:3.6.1-jdk-8-alpine
volumes:
# maven
path: /root/.m2
# 挂载宿主机的目录
path: /home
commands: maven 工程
# 开始打包
PRENAME,APPNAME 这两个参数死活取不出来,是我哪里用错了么 
看完很有用,谢谢
因为按照你配置的端口访问不了,我按照官网提供的参考配置配的端口同样访问不了。我不知道问题出在哪,因为我是 github+drone,你是 gitea+drone,网上搜了好多参考配置都没用,折腾一天了可太难了 