按 Enter 键跳转到正文

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 IDClient 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 仓库关联才能触发流水线,需先「激活」项目:

  1. 进入 Drone 控制台首页
    • 登录后,会显示你 Gitee 账号下的所有仓库列表(根据 OAuth 权限获取)。
  2. 激活目标项目
    • 找到你需要配置 CI/CD 的仓库(例如 my-app),点击仓库卡片右侧的 ACTIVATE 按钮并Trusted
    • 激活后,Drone 会自动为该仓库添加 Webhook(用于监听代码推送、PR 等事件),后续代码变动会自动触发流水线。

4.2 配置项目密钥(可选,用于部署等敏感操作)

如果你的流水线需要访问敏感信息(如服务器 SSH 密钥、数据库密码),需在 Drone 中配置「密钥」(Secrets),避免明文暴露:

  1. 进入项目设置:
    • 点击已激活的项目 → 右上角 Settings(齿轮图标)。
  2. 添加密钥:这些密钥可在流水线配置文件(.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

六、 提交代码触发流水线

  1. 将 .drone.yml 提交到 Gitee 仓库:
    1git add .drone.yml
    2git commit -m "Add Drone pipeline"
    3git push origin main
    
  2. 在 Drone 控制台查看流水线执行:
    • 进入项目页面,会看到一条新的构建记录(状态为「running」),点击记录可查看实时日志:
    • 绿色步骤表示成功,红色表示失败。
    • 点击步骤名称可查看详细输出(如编译错误、测试结果)。

七、 管理构建任务

  1. 重新运行流水线:
    • 若构建失败,可在构建记录页面点击 RESTART 重新运行,无需再次提交代码。
  2. 取消正在运行的任务:
    • 点击构建记录页面的 STOP 按钮,终止当前流水线。
  3. 查看历史构建:
    • 项目首页会显示所有历史构建记录,可按时间、状态筛选。

八 、其他操作(可选)

  1. 关闭项目自动触发:
    • 若需临时禁用流水线,在项目 Settings 中关闭 Auto-cancel redundant builds 或直接 DEACTIVATE 项目(保留配置,不再监听事件)。
  2. 配置分支保护:
    • 结合 Gitee 的分支保护规则,要求流水线成功后才能合并 PR(需在 Gitee 仓库设置中配置)。
  3. 集成通知:
    • 在 .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 实现代码提交后的自动化测试、编译和部署。核心是通过 .drone.yml 定义流水线逻辑,Drone 会根据配置自动执行并反馈结果。

发表评论