但行好事,莫问前程
前言
本文不只是配置文件的堆砌,也解释是什么和为什么,希望大家能耐心学习😽。
现在的项目大多通过各种 CI/CD工具 (例如著名的 Jenkins、 gitLab,github推出的 github actions)来进行 自动化部署。
它们已成为市场主流,是项目基建中不可或缺的一环。
开发人员只需开发完成后,一个代码推送/合并,项目便会自动部署到服务器上运行,呈现给用户。

持续部署(Continuous Deployment,CD):
- 指自动化部署已通过测试的代码到生产环境,以实现快速、可靠的软件交付。
- CD 流程包括自动化构建部署流程、自动化测试、环境配置管理等步骤,以确保部署的软件质量和稳定性。
- 目的是缩短软件交付周期,降低部署风险,提高部署的可重复性和一致性
相比于古早缓慢且充满风险的手动部署,它们能将项目 自动化的构建、测试和部署到线上环境以实现交付的高质量和效率。
无论你是什么方向的开发者,学习+使用它们都是一个极具性价比的选择。
接下来我们一起搭建自动化部署平台,如果对你有所帮助,还望点赞、收藏、关注三连😽。
简介
本文要分享的是后起之秀 Drone ,它免费、轻量、简洁、支持私有化,更重要的是它的 yaml写法 和 pipeline流水线 非常适合对运维陌生的同学去理解相关流程。
如果对 linux 和 docker 不熟悉的同学需要先简单了解相关知识,本文使用 docker compose 来编排容器。
Drone 深度集成了多个 SCM 网站,包括 GitHub、GitLab、Gitee等。它的每个构建都在一个隔离的 Docker 容器中运行;另外它也支持插件,可以使用你熟知的语言轻松的扩展它们。
当前一切都部署好后,只需在代码仓库目录下添加一个描述文件 .drone.yml,就可以完成 CI/CD 配置。
Drone 需要创建两个容器
Server: 负责任务调度、提供视图、用户权限配置 . . .Runner: 执行 Pipeline 具体任务、创建隔离的容器环境、上报日志和状态 . . .
流程 & 文档
我使用的服务器:4核4G - CentOS - 40G SSD (其实2核2G即可,Drone资源占用很少)
搭建自动化部署的流程如下:
- 配置
Github - OAuth Application - 安装、配置
Docker、Drone Server、Drone Runner - 编写
docker-compose.yml编排容器,用于管理Drone Server、Drone Runner - 了解
pipeline,了解常用插件,在代码仓库中加入.drone.yml - 推送代码测试打包效果
相关文档:
drone server 服务端 docs.drone.io/server/over...
drone runer linux docs.drone.io/runner/dock...
drone pieline 配置 docs.drone.io/pipeline/ov...
drone plugins plugins.drone.io/
常用指令:
docker compose down <image-name> 关闭指定容器(不指定则默认所有)
docker compose up -d <image-name> 启动指定容器(不指定则默认所有)
docker compose logs -f <image-name> 打印容器的日志
docker compose exec <image-name> bash 进入指定容器的shell
docker ps 查看正在运行的容器
docker images 查看下载的镜像
netstat -tulnp 显示进程与占用的端口
实践
Github OAuth
GitHub OAuth 的作用是: "让用户安全地授权第三方应用代表自己执行特定操作" 。
在Drone的使用场景中,它提供了:
- 🔐 安全登录 - 不用为Drone单独创建账号
- 🔄 自动同步 - Drone自动获取你的仓库列表
- ⚡ 自动触发 - Drone有权限设置webhook,代码推送即触发构建
- 🎯 权限可控 - 你可以随时在GitHub上撤销Drone的访问权限
配置
-
头像 -> Settings -> Developer settings -> OAuth Apps -> New OAuth App
-
填写项目名
-
HomePage URL ------ Github允许调用登录的URL,我们设置为drone server运行的端口
-
Authorization callback URL ------ 认证成功后的回调网址,在drone里为 url + /login

- 点击 New Secret

- 拿到
Client ID和Client Secret,记录下来!后续用于 Drone 的配置
127.0.0.1 只为预设,实际使用时请替换为自己的真实域名 或 IP+端口
Docker
bash
# 安装docker
sudo dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 启动指令
sudo systemctl start docker
sudo systemctl enable docker
# 测试指令
sudo docker run hello-world
# 配置镜像加速 + 重启服务
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
}
EOF
# 重启服务
sudo systemctl restart docker
镜像加速部分,个人服务器访问 "docker.1ms.run" 最快,大家结合自身情况配置
Docker Compose
Docker Compose 可以定义和运行多个 Docker 容器应用的工具。它允许你使用一个单独的文件(通常称为 docker-compose.yml)来配置应用程序的服务,然后使用该文件快速启动整个应用的所有服务。
Drone
使用docker安装drone的两个容器,Server端 - 控制调度和提供视图,Runner 端 - 执行流水线和上报状态
bash
docker pull drone/drone:latest
docker pull drone/drone-runner-docker:latest
同时创建一个共享密钥,用于 Server 和 Runner 之间的通信认证,使用此密钥填充环境变量 DRONE_RPC_SECRET
bash
openssl rand -hex 16
c1da0391axxxxxxxxxxxxxxxxx
drone-server
/opt/docker/docker-compose.yml
yml
services:
# drone 服务端
drone-server:
container_name: drone-server
image: drone/drone:latest
restart: always
ports:
# 端口映射
- 8082:80
- 4443:443
volumes:
# 挂载数据目录,持久化 Drone 的配置信息和数据库
# 容器 /data 目录 -> 宿主机当前 ./drone-data 目录
- ./drone-data:/data
environment:
# Git OAuth - Client ID
- DRONE_GITHUB_CLIENT_ID=Ov23lxxxxxxxxx
# Git OAuth - Client Secret
- DRONE_GITHUB_CLIENT_SECRET=d60645938xxxxxxxxxxxxxxxxxxxxx
# Drone Server 和 Runner 之间的 RPC 认证密钥,需保持一致
- DRONE_RPC_SECRET=c1da0391axxxxxxxxxxxxxxxxx
# Drone Server的公网地址
- DRONE_SERVER_HOST=<服务器的公网IP>:<端口>
# 通信协议
- DRONE_SERVER_PROTO=http
# 创建管理员账户
- DRONE_USER_CREATE=username:XiwE1,admin:true
-
ports - 为宿主机与容器的端口映射
-
DRONE_GITHUB_CLIENT_ID 和 DRONE_GITHUB_CLIENT_SECRET
- 对应上文
Git OAuth的Client ID和Client Secret,用于身份认证
- 对应上文
-
DRONE_RPC_SECRET - 是刚刚生成的共享密钥,用于 Server 与 Runner 通信
-
DRONE_SERVER_HOST - 改为服务器的真实IP和设置运行的端口
-
DRONE_SERVER_PROTO - 我只用到了 http,如有证书可设置 https
-
DRONE_USER_CREATE - 设置账户,name 为 github 账号名
此时我们启动服务
docker compose up -d drone-server
访问对应的公网网址,完成登录后(记得在Github修改 homepageURL + Authorization callback URL),即可看到自己仓库的所有项目。

我们选中一个测试项目的进行激活。

可以看到 github - 项目 - webhooks 已经激活了。

对项目进行简单的配置 Trusted -> SAVE。

drone-runer
/opt/docker/docker-compose.yml
yml
# drone 执行者(runer)
drone-runner:
container_name: drone-runner
image: drone/drone-runner-docker:latest
restart: always
ports:
- 3000:3000
volumes:
# 允许 Runner 在宿主机上操作 Docker 容器
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_RPC_PROTO=http
# 与 drone server 的container_name一致
- DRONE_RPC_HOST=drone-server
# Drone Server 和 Runner 之间的 RPC 认证密钥,需保持一致
- DRONE_RPC_SECRET=c1da0391xxxxxxxxxxxxxxxx
# 设置并发任务数上限
- DRONE_RUNNER_CAPACITY=3
- DRONE_RUNNER_NAME=drone-runner
depends_on:
- drone-server
- volumes - runner 执行流水线时需要不断地创建镜像容器,需要允许其操作 Docker
- DRONE_RPC_HOST - 同服务器可内部访问使用
container-name即可,如果跨服务器请填写 Drone Server 的域名 或 IP+端口 - DRONE_RPC_SECRET - 共享密钥,与Server保持一致
自动构建与部署等功能都依赖于 Drone Runner。

pipeline & .drone.yml
流水线(Pipeline)在软件工程中,特别是在持续集成和持续部署(CI/CD)中,是一个自动化流程,它将软件从代码到交付的多个步骤串联起来。
每个步骤都会完成一个特定的任务(例如编译、测试、部署),并且这些步骤按顺序执行,如果其中一个步骤失败,整个流程就会停止,从而保证软件质量。
简单来说,Pipeline 是把手动重复的软件发布过程,变成全自动的标准化流水线。无需人工干预,提高了效率并减少了人为错误。
而 YAML 是流水线的「说明书」,语法易于阅读和表达,能用结构化的文字描述整个自动化流程。
Drone 通过在项目的根目录中放置 .drone.yml 文件来配置流水线。

关于 .drone.yml 文件,通常有以下规则:
- 每个配置文件都以
kind: pipeline开头 - 需要指定执行器类型 ,例如Docker(
type: docker) - 需要设置 触发条件(Trigger) ,控制管道在何时 运行。最常用的是代码的
push事件 - 步骤(Steps)
- 管道由一个或多个步骤组成,每个步骤代表一个独立的任务(例如安装依赖、构建、测试、部署)。
- 每个步骤通常需要指定:
- 名称(name) :步骤标识,例如
build、deploy - 镜像(image) :执行任务的Docker镜像,这决定了步骤的运行环境
- 命令(commands) :在容器内执行的Shell命令序列。
- 名称(name) :步骤标识,例如
- 挂载卷(Volumes) ,用于在步骤之间持久化数据 或与宿主机共享文件
- ...
官方文档 docs.drone.io/pipeline/ov...
我们可以在steps里集成插件,drone plugins plugins.drone.io/
例如 用于通知构建状态的 slack,用于文件传输的 rsync,发布资源到S3的 AWS S3/AWS S3 Sync,等等。
我的项目(React + Yarn + Vite)构建配置如下:
./.drone.yml
yml
# 定义一个管道
kind: pipeline
# 定义管道类型
# 使用Docker执行器运行流水线
type: docker
name: default
# drone启动时,都会先执行clone代码操作,将对应仓库代码拉取到/drone/src目录下
clone:
# 重试以防网络问题导致clone失败
retries: 2
trigger:
branch:
- main
volumes:
# 将node_modules缓存到宿主机指定目录下
# 避免重新install延迟或者失败
- name: node_modules
host:
path: /home/drone/cache/fe/node_modules
# - name: pnpm-cache
# host:
# path: /home/drone/cache/fe/pnpm-store
# 挂载Docker套接字
- name: docker-sock
host:
path: /var/run/docker.sock
- name: admin-website
host:
path: /home/admin-website
steps:
# 编译阶段
- name: build
image: node:23
volumes:
- name: node_modules
# 挂载到容器内的路径
# 宿主机 node_modules -> 挂载到容器/drone/src/node_modules目录
path: /drone/src/node_modules
# - name: pnpm-cache
# path: /drone/src/.pnpm-store
commands:
- echo "============构建前的文件==============="
- pwd
- ls -alt
- echo "======================================"
- yarn --version || npm install -g yarn
- yarn install --frozen-lockfile
- yarn build
- echo "============构建后的产物==============="
- ls -la dist || exit 1
# 部署阶段
- name: deploy
image: drillster/drone-rsync
network_mode: host # 使用宿主机网络
settings:
hosts:
- localhost
# 或者服务器ip
user: root
key:
from_secret: deploy_ssh_secret
port: 22
source: dist/
target: /home/admin-website
# 如果在同一个服务器,可以把代码直接编译进挂载目录或者移入挂载目录
# - name: deploy
# image: alpine:latest
# volumes:
# - name: admin-website
# # 在容器内提供target目录 挂载到宿主机的host目录下
# path: /target
# commands:
# - apk add --no-cache rsync
# # 将容器内的dist目录同步到target目录,给volumes挂载
# - rsync -av --delete /drone/src/dist/ /target/
# # 验证文件是否复制成功
# - ls -la /target/ || exit 1
测试自动部署
至此我们就大功告成,可以进行测试了,现在修改代码后 push 远程 main 分支,即可触发自动构建。
改一下项目版本号试试

可以看到任务很快就完成了

访问网站(记得配置 nginx 代理)

结语
整套流程下来并不困难,但需要开发生涯中的多种知识为基础,并加以应用,理解完整的产品开发流程。
希望前端开发的思维不再局限于编码,从局部到全局,从编码到交付,做一个能独立交付产品的程序员。
如果公司里正好缺少对应的基建,便是你大展身手的机会。
还有很多细节值得我们讨论:
- 镜像构建时如何缓存,避免重复的无效构建
- 如何将项目直接部署到多个服务器运行,而不需要多次配置nginx
- 部署后出现问题怎么快速回滚
- 自动化测试
- . . .
大家感兴趣的话,再写一文讨论。
不要光看不实践哦~ 希望本文能对你有所帮助
持续更新前端知识,脚踏实地不水文,真的不关注一下吗~
写作不易,如果有收获还望 点赞+收藏 🌹
才疏学浅,如有问题或建议还望指教~