588_Drone CI持续集成
一句话概述:Drone CI 是容器原生的持续集成平台,每个构建步骤都在独立 Docker 容器中运行,配置简单(一个 YAML 文件),自托管免费,是轻量级 CI/CD 的好选择。
核心知识点表
| 概念 | 白话解释 |
|---|
| Pipeline | 流水线,代码从提交到部署的自动化过程 |
| Step | 步骤,流水线中的一个操作(如测试、构建、部署) |
| Runner | 执行器,实际运行构建步骤的组件 |
| Plugin | 插件,预配置的 Docker 镜像,直接用于常见任务 |
| Secret | 密钥,安全存储的敏感信息(如 API Key) |
| Trigger | 触发器,决定什么事件触发构建(push/PR/tag) |
安装配置
Docker Compose 部署
# docker-compose.yml
services:
drone-server:
image: drone/drone:latest # Drone 服务端
container_name: drone
restart: always
ports:
- "8080:80" # Web 界面
- "8443:443" # HTTPS
volumes:
- ./drone-data:/data # 数据持久化
environment:
- DRONE_GITEA_SERVER=https://git.example.com # Gitea 地址
- DRONE_GITEA_CLIENT_ID=your-client-id # OAuth App ID
- DRONE_GITEA_CLIENT_SECRET=your-secret # OAuth App Secret
- DRONE_RPC_SECRET=super-secret-key # Server-Runner 通信密钥
- DRONE_SERVER_HOST=drone.example.com # Drone 外部地址
- DRONE_SERVER_PROTO=https # 协议
- DRONE_USER_CREATE=username:admin,admin:true # 管理员
drone-runner:
image: drone/drone-runner-docker:latest # Docker Runner
container_name: drone-runner
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Docker socket
environment:
- DRONE_RPC_PROTO=http # 通信协议
- DRONE_RPC_HOST=drone-server # Server 地址
- DRONE_RPC_SECRET=super-secret-key # 必须与 Server 一致
- DRONE_RUNNER_CAPACITY=2 # 同时执行 2 个构建
- DRONE_RUNNER_NAME=my-runner # Runner 名称
depends_on:
- drone-server
# 先生成通信密钥
openssl rand -hex 32 # 生成随机密钥
docker compose up -d # 启动
配置 Git 平台 OAuth
# 以 Gitea 为例:
# 1. Gitea → 用户设置 → 应用 → 创建 OAuth2 应用
# 2. 应用名:Drone CI
# 3. 重定向 URL:https://drone.example.com/login
# 4. 获取 Client ID 和 Client Secret
# 5. 填入 Docker Compose 的环境变量中
# 支持的 Git 平台:
# GitHub | GitLab | Gitea | Gogs | Bitbucket
基本使用
配置流水线(.drone.yml)
# 在仓库根目录创建 .drone.yml
kind: pipeline # 资源类型:流水线
type: docker # 执行方式:Docker
name: default # 流水线名称
steps:
- name: test # 步骤1:测试
image: node:20 # 使用 Node.js 20 镜像
commands: # 执行命令
- npm install # 安装依赖
- npm test # 运行测试
- name: build # 步骤2:构建
image: node:20
commands:
- npm run build # 构建项目
when:
branch: main # 只在 main 分支执行
- name: deploy # 步骤3:部署
image: plugins/docker # 使用 Docker 插件
settings:
repo: myregistry/myapp # 镜像仓库
tags: latest # 标签
username:
from_secret: docker_username # 从密钥读取用户名
password:
from_secret: docker_password # 从密钥读取密码
when:
branch: main # 只在 main 分支
event: push # 只在 push 事件
常用插件
# === Docker 构建和推送 ===
- name: publish
image: plugins/docker
settings:
repo: registry.example.com/myapp
tags: ${DRONE_TAG} # 使用 Git tag 作为镜像 tag
registry: registry.example.com
username: { from_secret: reg_user }
password: { from_secret: reg_pass }
# === 发送通知 ===
- name: notify
image: plugins/slack
settings:
webhook: { from_secret: slack_webhook }
channel: deployments
when:
status: [success, failure] # 成功和失败都通知
# === 部署到服务器(SSH) ===
- name: deploy-ssh
image: appleboy/drone-ssh
settings:
host: { from_secret: deploy_host }
username: deploy
key: { from_secret: ssh_key }
script:
- cd /app && docker compose pull && docker compose up -d
# === 发送钉钉通知 ===
- name: dingtalk
image: lddsb/drone-dingtalk-message
settings:
token: { from_secret: dingtalk_token }
type: markdown
管理密钥
# 方法1:Web 界面
# 仓库设置 → Secrets → 添加密钥
# 方法2:CLI
drone secret add \
--repository user/repo \ # 仓库
--name docker_password \ # 密钥名
--data your-password # 密钥值
高级用法
条件触发
# 只在特定条件下执行步骤
steps:
- name: deploy-prod
image: plugins/docker
when:
branch: main # 只在 main 分支
event: tag # 只在打 tag 时
ref: refs/tags/v* # tag 以 v 开头
status: success # 前面步骤都成功
多流水线
# 可以在一个 .drone.yml 中定义多个流水线
---
kind: pipeline
type: docker
name: test
steps:
- name: test
image: node:20
commands: [npm test]
---
kind: pipeline
type: docker
name: deploy
steps:
- name: deploy
image: plugins/docker
settings: { ... }
depends_on: [test] # 依赖 test 流水线
服务容器(如数据库)
kind: pipeline
type: docker
name: integration-test
services:
- name: postgres # 启动 PostgreSQL 服务
image: postgres:16
environment:
POSTGRES_DB: testdb
POSTGRES_PASSWORD: testpass
steps:
- name: test
image: node:20
environment:
DATABASE_URL: postgres://postgres:testpass@postgres:5432/testdb
commands:
- npm install
- npm run test:integration # 集成测试连接上面的 PostgreSQL
常见报错
| 报错信息 | 原因 | 解决方案 |
|---|
runner not connected | Runner 未连接到 Server | 检查 RPC_SECRET 是否一致 |
unauthorized | 仓库未激活 | 在 Drone 面板中激活仓库 |
yaml: invalid | .drone.yml 语法错误 | 用 drone lint 检查 |
OCI runtime error | Docker 镜像拉取失败 | 检查镜像名和网络 |
secret not found | 密钥未配置 | 在仓库设置中添加密钥 |
速查表
# === CLI 安装 ===
curl -L https://github.com/harness/drone-cli/releases/latest/download/drone_linux_amd64.tar.gz | tar zx
sudo mv drone /usr/local/bin/
# === CLI 常用命令 ===
drone build ls user/repo # 列出构建
drone build info user/repo 1 # 构建详情
drone build restart user/repo 1 # 重新构建
drone repo ls # 列出仓库
drone secret ls --repository user/repo # 列出密钥
drone lint .drone.yml # 检查配置语法
# === 内置环境变量 ===
DRONE_BRANCH # 分支名
DRONE_COMMIT # 提交 SHA
DRONE_TAG # Git tag
DRONE_BUILD_NUMBER # 构建编号
DRONE_REPO # 仓库名
DRONE_BUILD_STATUS # 构建状态
同类对比
| 特性 | Drone CI | Jenkins | Woodpecker CI | Gitea Actions |
|---|
| 配置方式 | YAML | Jenkinsfile | YAML | YAML(GH兼容) |
| 资源占用 | 轻量 | 重(Java) | 极轻 | 内置 |
| 容器原生 | 是 | 插件 | 是 | 是 |
| 插件生态 | 丰富 | 最丰富 | 发展中 | GH Actions兼容 |
| 学习曲线 | 低 | 高 | 低 | 低 |
| 维护状态 | Harness接管 | 活跃 | 活跃 | 活跃 |
选型建议:轻量容器化 CI 选 Drone;用 Gitea 则直接用 Gitea Actions(兼容 GitHub Actions);需要最大灵活性选 Jenkins;Drone 的社区分支 Woodpecker CI 更活跃。