Drone CICD自动化部署指南
一、Drone核心优势与架构设计
1.1 为什么选择Drone
Drone作为轻量级云原生CI/CD工具,相比Jenkins具有显著优势:
资源占用低:基于Docker容器化运行,单个Pipeline平均内存消耗<100MB
云原生支持:原生集成Kubernetes、Docker等云原生技术栈
配置即代码:完全通过.drone.yml定义流程,版本可控
高性能:测试显示并发构建能力比Jenkins高3-5倍16
1.2 企业级架构设计
1[Gitee/GitHub] → [Drone Server] → [Docker Runner] (开发环境)
2 ↘ [K8s Runner] (生产环境)
3 ↘ [SSH Runner] (特殊场景)
二、 注册 OAuth 应用 (Gitee为例)
登录 Gitee → 点击右上角头像 → 设置 → 第三方应用 → 创建应用
填写应用信息:
- 应用名称:
Drone CI(自定义) - 应用描述:
Drone CI/CD 工具(自定义) - 授权回调地址:
http://你的服务器IP或域名/login(必须正确,否则无法登录) - 应用主页:
http://你的服务器IP或域名 - 权限选择:(最少权限原则)user_info,projects,pull_requests,hooks
- 应用名称:
提交后,记录生成的 Client ID 和 Client Secret(后续配置需要)
三、安装 Drone 服务器和 Runner
Drone 由两部分组成:
- Drone Server:管理项目、接收仓库事件、协调任务
- Drone Runner:执行流水线任务(编译、测试、部署等)
3.1 手动启动 Drone Server
1docker run -d \
2 --name drone-server \
3 --restart always \
4 -p 80:80 \ # 端口映射(生产环境建议加 HTTPS)
5 -v /var/lib/drone:/data \ # 数据持久化
6 -e DRONE_RPC_SECRET=your_agent_secret \ # 自定义密钥(与 Runner 保持一致)
7 -e DRONE_GITEE_CLIENT_ID=你的Gitee Client ID \ # 替换为 Gitee 应用的 Client ID
8 -e DRONE_GITEE_CLIENT_SECRET=你的Gitee Client Secret \ # 替换为 Gitee 应用的 Secret
9 -e DRONE_GITEE_SERVER=https://gitee.com \ # Gitee 服务器地址(固定)
10 -e DRONE_SERVER_HOST=你的服务器IP或域名 \ # Drone 访问地址(如 drone.example.com)
11 -e DRONE_SERVER_PROTO=http \ # 协议(http 或 https)
12 -e DRONE_USER_CREATE=username:你的Gitee用户名,admin:true \ # 设置 Gitee 用户名作为管理员
13 drone/drone:2.16
DRONE_AGENT_SECRET 可以简单用命令生成openssl rand -hex 16
Drone Server 默认监听容器内的 80 端口(HTTP)和 443 端口(HTTPS,若配置证书),你可以通过 Docker 的端口映射映射(-p 参数)自定义宿主机的端口。
3.2 手动启动 Drone Runner
1docker run -d \
2 --name drone-runner \
3 --restart always \
4 -v /var/run/docker.sock:/var/run/docker.sock \ # 必须挂载,允许操作 Docker
5 -e DRONE_RUNNER_NAME=my-gitee-runner \ # Runner 名称(自定义)
6 -e DRONE_RUNNER_CAPACITY=2 \ # 最大并行任务数
7 -e DRONE_RPC_SECRET=your_agent_secret \ # 与 Server 的密钥一致
8 -e DRONE_RPC_HOST=你的服务器IP或域名 \
9 -e DRONE_RPC_PROTO=http \
10 drone/drone-runner-docker:1.8
3.3 验证安装
1docker ps | grep drone
2# 若 drone-server 和 drone-runner 状态为 Up,则启动成功。
访问控制台:
打开浏览器访问 http://你的服务器IP:端口,会出现Drone页面,点击CONTINUE。首次登录需授权 Drone 访问你的 Gitee 账号和仓库,授权后即可进入控制台。
四、 激活项目、配置项目秘钥
成功打开 Drone 控制台后,接下来的核心操作是激活项目、配置流水线和管理构建任务。以下是详细步骤:
4.1 激活代码仓库(首次使用)
Drone 需与你的 Gitee 仓库关联才能触发流水线,需先「激活」项目:
- 进入 Drone 控制台首页
- 登录后,会显示你 Gitee 账号下的所有仓库列表(根据 OAuth 权限获取)。
- 激活目标项目
- 找到你需要配置 CI/CD 的仓库(例如 my-app),点击仓库卡片右侧的 ACTIVATE 按钮并Trusted
- 激活后,Drone 会自动为该仓库添加 Webhook(用于监听代码推送、PR 等事件),后续代码变动会自动触发流水线。
4.2 配置项目密钥(可选,用于部署等敏感操作)
如果你的流水线需要访问敏感信息(如服务器 SSH 密钥、数据库密码),需在 Drone 中配置「密钥」(Secrets),避免明文暴露:
- 进入项目设置:
- 点击已激活的项目 → 右上角 Settings(齿轮图标)。
- 添加密钥:这些密钥可在流水线配置文件(.drone.yml)中通过 from_secret: 密钥名 引用。
- 在 Secrets 区域,点击 Add Secret。
- 填写 Name(如 server_ssh_key)和 Value(如实际的 SSH 私钥内容)。
- 点击 Save 保存。
五、 编写流水线配置文件(核心)
在你的代码仓库根目录创建 .drone.yml 文件,定义自动化流程(如测试、编译、部署)。
示例(Golang 项目):
1# 定义流水线类型和名称
2kind: pipeline
3type: docker
4name: golang-enterprise-cd
5
6# 触发条件:仅在 main 分支和 release/* 分支推送时执行
7trigger:
8 branch:
9 - main
10 - release/*
11 event:
12 - push
13 - tag # 支持标签触发(如发布版本时)
14
15# 工作空间配置:缓存依赖,加速构建
16workspace:
17 path: /go/src/github.com/your-org/your-golang-project # 项目路径(根据实际调整)
18
19# 流水线步骤
20steps:
21 # 步骤1:代码质量检查(静态分析)
22 - name: code-quality
23 image: golangci/golangci-lint:v1.54-alpine # 代码检查工具
24 commands:
25 - golangci-lint run ./... # 运行所有代码检查规则
26 depends_on: [ ] # 无依赖,最先执行
27
28 # 步骤2:下载依赖并缓存
29 - name: fetch-dependencies
30 image: golang:1.21-alpine
31 commands:
32 - go mod tidy # 整理依赖
33 - go mod vendor # 导出依赖到vendor目录(便于缓存)
34 volumes:
35 - name: go-mod-cache # 挂载缓存卷
36 path: /go/pkg/mod
37 depends_on: [ code-quality ] # 依赖代码检查步骤
38
39 # 步骤3:单元测试并生成覆盖率报告
40 - name: unit-test
41 image: golang:1.21-alpine
42 commands:
43 - go test -v -race -coverprofile=coverage.out ./... # 运行测试(含数据竞争检测)
44 - go tool cover -func=coverage.out # 输出覆盖率摘要
45 volumes:
46 - name: go-mod-cache
47 path: /go/pkg/mod
48 depends_on: [ fetch-dependencies ]
49
50 # 步骤4:编译(分环境构建)
51 - name: build
52 image: golang:1.21-alpine
53 commands:
54 # 编译Linux版本(生产环境)
55 - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X main.version=${DRONE_TAG:-latest}" -o app-linux ./cmd/server
56 # 编译Windows版本(可选,用于跨平台发布)
57 - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -X main.version=${DRONE_TAG:-latest}" -o app-windows.exe ./cmd/server
58 # 查看编译产物
59 - ls -lh app-linux app-windows.exe
60 volumes:
61 - name: go-mod-cache
62 path: /go/pkg/mod
63 depends_on: [ unit-test ]
64 when:
65 event: [ push, tag ] # 推送和标签事件都执行
66
67 # 步骤5:构建Docker镜像(生产环境)
68 - name: build-docker
69 image: docker:24.0.5
70 commands:
71 # 登录Docker仓库(如私有仓库或Docker Hub)
72 - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
73 # 构建镜像(标签包含Git commit和版本号)
74 - docker build -t your-registry/your-golang-app:${DRONE_TAG:-$DRONE_COMMIT} -t your-registry/your-golang-app:latest .
75 # 推送镜像
76 - docker push your-registry/your-golang-app:${DRONE_TAG:-$DRONE_COMMIT}
77 - docker push your-registry/your-golang-app:latest
78 volumes:
79 - name: docker-sock # 挂载Docker套接字
80 path: /var/run/docker.sock
81 environment:
82 DOCKER_USERNAME:
83 from_secret: docker_username # Docker仓库用户名(从密钥获取)
84 DOCKER_PASSWORD:
85 from_secret: docker_password # Docker仓库密码(从密钥获取)
86 depends_on: [ build ]
87 when:
88 branch: [ main ] # 仅主分支构建Docker镜像
89
90 # 步骤6:部署到生产环境(通过SSH)
91 - name: deploy-production
92 image: appleboy/drone-ssh
93 settings:
94 host:
95 from_secret: prod_server_host # 生产服务器地址
96 username:
97 from_secret: prod_server_user # 服务器用户名
98 key:
99 from_secret: prod_server_ssh_key # SSH私钥
100 port: 22
101 script:
102 # 切换到部署目录
103 - cd /opt/your-golang-app
104 # 拉取最新镜像
105 - docker pull your-registry/your-golang-app:${DRONE_TAG:-$DRONE_COMMIT}
106 # 停止旧容器
107 - docker-compose down || true
108 # 启动新容器(使用docker-compose管理)
109 - docker-compose up -d
110 # 检查服务状态
111 - docker-compose ps
112 depends_on: [ build-docker ]
113 when:
114 branch: [ main ] # 仅主分支部署到生产环境
115 event: [ push, tag ]
116
117 # 步骤7:发送构建结果通知(钉钉/企业微信)
118 - name: send-notification
119 image: appleboy/drone-webhook
120 settings:
121 urls:
122 from_secret: notification_webhook # 通知Webhook地址
123 content_type: application/json
124 body: |
125 {
126 "msgtype": "text",
127 "text": {
128 "content": "Golang项目构建结果:${DRONE_BUILD_STATUS}\n项目:${DRONE_REPO_NAME}\n分支:${DRONE_BRANCH}\n构建链接:${DRONE_BUILD_LINK}"
129 }
130 }
131 when:
132 status: [ success, failure ] # 成功或失败都通知
133 depends_on: [ deploy-production ]
134
135# 定义缓存卷(加速构建)
136volumes:
137 - name: go-mod-cache
138 temp: { } # 临时缓存(也可使用持久化卷)
139 - name: docker-sock
140 host:
141 path: /var/run/docker.sock # 挂载宿主机Docker套接字
示例 (PHP 项目):
1# 定义流水线类型和名称
2kind: pipeline
3type: docker
4name: php-enterprise-cd
5
6# 触发条件:主分支、开发分支和标签事件
7trigger:
8 branch:
9 - main
10 - develop
11 - feature/*
12 event:
13 - push
14 - pull_request
15 - tag
16
17# 工作空间配置
18workspace:
19 path: /var/www/html # PHP项目默认工作目录
20
21# 流水线步骤
22steps:
23 # 步骤1:代码风格检查(PHP_CodeSniffer)
24 - name: code-style
25 image: php:8.2-cli-alpine
26 commands:
27 # 安装代码检查工具
28 - curl -L https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar -o phpcs
29 - chmod +x phpcs
30 # 检查代码规范(使用PSR-12标准)
31 - ./phpcs --standard=PSR12 src/ tests/
32 depends_on: [ ]
33
34 # 步骤2:安装PHP依赖(Composer)
35 - name: install-dependencies
36 image: composer:2.5-alpine
37 commands:
38 - composer install --no-dev --optimize-autoloader # 生产环境依赖(无dev包)
39 - composer dump-autoload -o # 优化自动加载
40 volumes:
41 - name: composer-cache # 缓存Composer依赖
42 path: /tmp/composer-cache
43 depends_on: [ code-style ]
44
45 # 步骤3:单元测试(PHPUnit)
46 - name: unit-test
47 image: php:8.2-cli-alpine
48 commands:
49 # 安装PHP扩展和测试工具
50 - docker-php-ext-install pdo_mysql
51 - composer install # 安装开发依赖(含PHPUnit)
52 # 运行测试并生成报告
53 - vendor/bin/phpunit --coverage-text --configuration phpunit.xml
54 depends_on: [ install-dependencies ]
55 when:
56 event: [ pull_request, push ] # PR和推送时执行测试
57
58 # 步骤4:静态代码分析(PHPStan)
59 - name: static-analysis
60 image: php:8.2-cli-alpine
61 commands:
62 - composer require --dev phpstan/phpstan # 安装分析工具
63 - vendor/bin/phpstan analyse src/ --level=7 # 严格级别7(最高8)
64 depends_on: [ install-dependencies ]
65
66 # 步骤5:构建前端资源(若有Node.js依赖)
67 - name: build-frontend
68 image: node:18-alpine
69 commands:
70 - cd resources/assets # 进入前端资源目录
71 - npm install --production
72 - npm run build # 编译JS/CSS(如Webpack)
73 depends_on: [ static-analysis ]
74 when:
75 branch: [ main, develop ] # 仅主分支和开发分支构建前端
76
77 # 步骤6:构建Docker镜像(含Nginx+PHP-FPM)
78 - name: build-docker
79 image: docker:24.0.5
80 commands:
81 - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
82 # 构建镜像(区分环境标签)
83 - |
84 if [ "$DRONE_BRANCH" = "main" ]; then
85 TAG="production-${DRONE_COMMIT:0:8}"
86 elif [ "$DRONE_BRANCH" = "develop" ]; then
87 TAG="staging-${DRONE_COMMIT:0:8}"
88 else
89 TAG="feature-${DRONE_BRANCH##*/}-${DRONE_COMMIT:0:8}"
90 fi
91 - docker build -t your-registry/your-php-app:$TAG .
92 - docker push your-registry/your-php-app:$TAG
93 volumes:
94 - name: docker-sock
95 path: /var/run/docker.sock
96 environment:
97 DOCKER_USERNAME:
98 from_secret: docker_username
99 DOCKER_PASSWORD:
100 from_secret: docker_password
101 depends_on: [ build-frontend ]
102 when:
103 event: [ push, tag ]
104
105 # 步骤7:部署到生产环境(使用Ansible自动化)
106 - name: deploy-production
107 image: williamyeh/ansible:alpine3
108 commands:
109 # 配置Ansible(连接生产服务器)
110 - mkdir -p ~/.ssh
111 - echo "$PROD_SSH_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
112 - ansible-playbook -i ansible/inventory/prod.yml ansible/deploy.yml -e "image_tag=${TAG}"
113 environment:
114 PROD_SSH_KEY:
115 from_secret: prod_server_ssh_key
116 TAG: production-${DRONE_COMMIT:0:8}
117 depends_on: [ build-docker ]
118 when:
119 branch: [ main ]
120 event: [ push, tag ]
121
122 # 步骤8:部署到测试环境(开发分支)
123 - name: deploy-staging
124 image: appleboy/drone-ssh
125 settings:
126 host:
127 from_secret: staging_server_host
128 username:
129 from_secret: staging_server_user
130 key:
131 from_secret: staging_server_ssh_key
132 script:
133 - cd /opt/your-php-app
134 - docker-compose pull
135 - docker-compose up -d
136 depends_on: [ build-docker ]
137 when:
138 branch: [ develop ] # 开发分支部署到测试环境
139
140 # 步骤9:发送通知到企业微信
141 - name: notify
142 image: feiyu563/drone-wechat-work:latest
143 settings:
144 corp_id:
145 from_secret: wechat_corp_id
146 corp_secret:
147 from_secret: wechat_corp_secret
148 agent_id: 1000002
149 to_user: "@all"
150 message: "PHP项目构建${DRONE_BUILD_STATUS}\n仓库: ${DRONE_REPO}\n分支: ${DRONE_BRANCH}\n链接: ${DRONE_BUILD_LINK}"
151 when:
152 status: [ success, failure ]
153
154# 缓存卷定义
155volumes:
156 - name: composer-cache
157 host:
158 path: /tmp/composer-cache # 宿主机缓存目录(可持久化)
159 - name: docker-sock
160 host:
161 path: /var/run/docker.sock
六、 提交代码触发流水线
- 将 .drone.yml 提交到 Gitee 仓库:
1git add .drone.yml 2git commit -m "Add Drone pipeline" 3git push origin main - 在 Drone 控制台查看流水线执行:
- 进入项目页面,会看到一条新的构建记录(状态为「running」),点击记录可查看实时日志:
- 绿色步骤表示成功,红色表示失败。
- 点击步骤名称可查看详细输出(如编译错误、测试结果)。
七、 管理构建任务
- 重新运行流水线:
- 若构建失败,可在构建记录页面点击 RESTART 重新运行,无需再次提交代码。
- 取消正在运行的任务:
- 点击构建记录页面的 STOP 按钮,终止当前流水线。
- 查看历史构建:
- 项目首页会显示所有历史构建记录,可按时间、状态筛选。
八 、其他操作(可选)
- 关闭项目自动触发:
- 若需临时禁用流水线,在项目 Settings 中关闭 Auto-cancel redundant builds 或直接 DEACTIVATE 项目(保留配置,不再监听事件)。
- 配置分支保护:
- 结合 Gitee 的分支保护规则,要求流水线成功后才能合并 PR(需在 Gitee 仓库设置中配置)。
- 集成通知:
- 在 .drone.yml 中添加邮件、钉钉、Slack 等通知步骤,例如构建失败时自动提醒:
1- name: notify 2 image: appleboy/drone-telegram 3 settings: 4 token: 5 from_secret: telegram_token 6 to: your_chat_id 7 when: 8 status: [success, failure] # 成功或失败都通知
- 在 .drone.yml 中添加邮件、钉钉、Slack 等通知步骤,例如构建失败时自动提醒:
通过以上步骤,即可利用 Drone 实现代码提交后的自动化测试、编译和部署。核心是通过 .drone.yml 定义流水线逻辑,Drone 会根据配置自动执行并反馈结果。
发表评论