部署三部曲:从 Jenkins 到 Drone 再到 Cloud Toolkit
约 3036 字大约 10 分钟
2026-09-14
背景:域名到期,一切从头
之前的服务器和域名到期了,到期之后我也一直没续——那段时间手头上没什么想部署的项目,就搁置了下来。
最近折腾 AI 项目(就是前面 RAG 知识库那套),前后端都写得差不多了,总不能在本地 localhost 自嗨一辈子,得找个地方把它挂上去。于是重新买了一台新服务器,注册了一个新域名,准备把整个项目正式部署上线。
服务器的配置不高,2 核 2G,跑个人项目够用,但经不起折腾。这个配置后面会反复成为「主角」——因为好几个方案就是被它否决掉的。
📷 图片位(待补充)
应放什么图:新服务器的云控制台截图,展示配置信息(2 核 2G、系统版本、带宽等),让读者对「舞台」有个直观印象。
这篇文章聊的是部署方式的选型过程——我先后试了三套方案,踩了不少坑,最终才定下来。下一篇再讲具体的部署脚本和前后端怎么跑起来。
为什么选 Docker 部署
在聊 CI/CD 工具之前,先把运行方式定了:Docker。
理由很朴素:
- 环境隔离——服务器上可能同时跑 Java 后端、Nginx、PostgreSQL、Python 引擎等多个服务,Docker 把它们各自关在容器里,互不干扰。升级某个服务不会影响其他服务,删掉容器也不会把宿主机搞得乱七八糟
- 可复现——
Dockerfile写好了,换一台机器也能秒级重建。服务器挂了不怕,重新拉起来就行 - 好管理——
docker ps一眼看清所有服务状态,docker logs查日志,docker restart重启,运维命令统一且简洁
对 2 核 2G 的机器来说,Docker 本身的开销几乎可以忽略——它不是虚拟机,没有 Hypervisor 那层,容器共享宿主机内核,内存额外开销也就几十兆。
关于 Docker Compose
有人会问为什么不用 Docker Compose 编排。对单台服务器、两三个服务的场景来说,一个统一部署脚本比 Compose 文件更灵活——后面第 18 篇会讲我写的统一脚本。当然如果服务多了,Compose 或者 K8s 才是正解。
部署工具的进化史
运行方式定了,接下来的问题是:代码怎么从我的笔记本跑到服务器上?
最原始的方式是手动操作:本地打包 → scp 传到服务器 → SSH 上去执行部署命令。偶尔部署一次还行,次数多了你就知道有多痛苦——步骤多、容易漏、每次都得记。
所以我想要一个自动化的流程:本地 git push,服务器自动拉取、构建、部署。也就是常说的 CI/CD。
我先后试了三套方案,每一套都有它好的地方,也都有它「不合适」的地方。
第一站:Jenkins —— 重型军火库
Jenkins 是 CI/CD 领域的老大哥,功能强大到没朋友。流水线、插件生态、社区支持,哪一样都是顶级的。
我也确实把它跑起来了。配好 Pipeline,写好 Jenkinsfile,git push 触发构建,自动打包,SSH 部署到服务器——整套流程行云流水。
📷 图片位(待补充)
应放什么图:Jenkins 的 Pipeline 配置页面截图,或者构建历史页面截图,展示「流水线确实跑起来了」的证据。
但问题很快就来了:内存扛不住。
Jenkins 本身是 Java 写的,启动就是吃内存大户。光 Jenkins 一个进程就占了将近 500MB-1GB 的内存,再加上构建时的 Maven/Gradle 进程、Docker 构建进程……2G 内存的服务器根本不够它霍霍。
最夸张的一次,Jenkins 正在构建后端项目,服务器的可用内存直接掉到几十兆,系统开始疯狂 swap,SSH 都连不上了。等它缓过来,构建早就超时失败。
小马拉大车
2 核 2G 跑 Jenkins,就像让一辆老年代步车去拉集装箱——不是拉不动,是拉到半路车架就散了。
Jenkins 适合团队项目、中大型服务器,但对我这种个人项目 + 乞丐版服务器的场景来说,它是那尊「容不下的大佛」。忍痛放弃。
第二站:Drone CI —— 轻量级选手
放弃了 Jenkins 之后,我找到了 Drone CI。
Drone 比 Jenkins 轻量得多——它本身就是一个 Go 写的二进制文件,跑在 Docker 容器里,内存占用小很多。配置文件是 YAML 格式(.drone.yml),比 Jenkinsfile 清爽,写起来也舒服。
我兴致勃勃地配好了 Drone,拉起了 Server + Runner,写好了 .drone.yml:
# .drone.yml 配置示例(已废弃,仅供展示)
kind: pipeline
type: docker
name: relax-web
steps:
- name: build
image: maven:3.9-eclipse-temurin-21
commands:
- mvn clean package -DskipTests
- name: deploy
image: docker
commands:
- docker build -t relax-web:latest .
- docker stop relax-web || true
- docker rm relax-web || true
- docker run -d --name relax-web --restart unless-stopped -p 8031:8031 relax-web:latest📷 图片位(待补充)
应放什么图:Drone CI 的 Web 界面截图,或者 .drone.yml 文件内容截图,展示配置有多简洁。
轻量、优雅、看起来很美好。但一跑起来,服务器直接冒烟了。
问题不在 Drone 本身,而在 构建过程。我的 relax-box 项目(就是你现在看到的这个博客站)是 VuePress 构建的,整个站点的 Markdown 文件加上图片资源非常多,npm run build 的时候:
- CPU 直接打满 —— Node.js 构建时疯狂编译 Markdown、渲染页面、打包资源
- 磁盘 IO 打满 —— 大量文件读写操作
- 内存飙升 —— Vite 打包进程 + 各种插件同时吃内存
三项同时爆表,2 核 2G 的服务器当场就「干冒烟」了。别说继续构建,整台机器都卡得跟幻灯片一样,SSH 断连,所有服务一起陪葬。
构建期间的服务器状态(回忆还原):
CPU: ██████████████████████ 100%
内存: ████████████████████░░ 95%
IO: ██████████████████████ 100%
状态: 已报废 ✗血泪教训
在低配服务器上搞 CI/CD 构建(Build),是一种自杀式行为。构建这个环节应该放在别的地方,服务器只负责部署(Deploy)——也就是拿到已经打好的包,把它跑起来。
Drone 本身没问题,是我选错了用法。它更适合「在独立构建服务器上跑 CI,然后推送到目标服务器部署」的两段式流程。但我就一台服务器,没条件搞这么复杂。
第二个方案,也排除了。
第三站:Alibaba Cloud Toolkit —— IDE 里的一键部署
碰了两次壁之后,我重新想了一下我到底需要什么:
- 不在服务器上构建 —— 构建在本地(或 CI 服务器)完成,服务器只负责跑
- 操作简单 —— 个人项目不值得搞一套完整的 CI/CD 基础设施
- 和开发流程无缝 —— 最好能在 IDE 里一键完成
然后我发现了 Alibaba Cloud Toolkit。
这个 IntelliJ IDEA 插件的工作流程特别简单:
本地 IDEA → 打包 → SCP 传到服务器 → SSH 执行部署命令整个操作在 IDE 里点几下就完成,不需要在服务器上装任何额外的 CI/CD 服务。
工作流程
- 在 IDEA 里配好服务器连接信息(SSH 地址、用户名、密钥)
- 配好部署规则:本地哪个文件传到服务器哪个目录,传完之后执行什么命令
- 点击 Deploy —— 打包、上传、部署一气呵成
这就是我要的方案:轻量、直接、不在服务器上吃资源。
📷 图片位(待补充)
应放什么图:Alibaba Cloud Toolkit 的部署配置界面截图,展示 Host 连接配置和 Deploy 配置(文件映射 + 部署命令),让读者看到配置有多直观。
不过这里有一个小插曲。
版本兼容问题
Alibaba Cloud Toolkit 插件目前还不支持 IntelliJ IDEA 2026.x 版本。我当前用的是 IDEA 2026.1,插件装不上。
你可以到官方插件版本页面查看最新的兼容情况:
Alibaba Cloud Toolkit Versions
如果你也遇到了版本不兼容的问题,有两个临时解决办法:
- 降级 IDEA 版本 —— 装一个插件支持的 IDEA 版本专门用来部署(我就这么干的)
- 手动执行脚本 —— 把 Cloud Toolkit 做的事拆成手动步骤,无非就是
scp+ssh,后面会讲统一部署脚本
希望官方后续能跟进新版本 IDEA 的适配。除此之外,这个方案用起来确实省心。
最终方案:Cloud Toolkit + 统一部署脚本
折腾了一圈,最终定下来的方案其实特别朴素:
- 构建在本地完成:前端
npm run build产出dist,后端mvn package产出jar - 传输用 Cloud Toolkit 或手动 SCP:把构建产物推到服务器的指定目录
- 部署用统一 Shell 脚本:服务器上的一个脚本自动识别项目类型,完成构建镜像、启动容器、清理旧版本等全部操作
完整部署链路:
本地开发机 服务器(2C2G)
┌─────────────┐ ┌──────────────────────┐
│ IDEA 打包 │ │ /opt/docker/projects/│
│ mvn package │──SCP/Toolkit──▶│ ├─ relax-web/ │
│ npm build │ │ │ ├─ *.jar │
└─────────────┘ │ │ ├─ Dockerfile │
│ │ ├─ start.sh │
│ │ ├─ deploy.conf │
│ │ └─ .env │
│ ├─ bookmark_box/ │
│ │ └─ dist/ │
│ └─ ... │
│ │
│ deploy.sh ◀── SSH 执行│
│ ├─ 识别前端 → Nginx│
│ └─ 识别后端 → Docker│
└──────────────────────┘这个方案的核心优势:
| 对比项 | Jenkins | Drone | Cloud Toolkit + 脚本 |
|---|---|---|---|
| 服务器内存占用 | 高(500MB+) | 中(100MB+) | 几乎为零 |
| 构建是否吃服务器资源 | 是 | 是 | 否(本地构建) |
| 操作复杂度 | 高 | 中 | 低 |
| 是否需要额外服务 | 是 | 是 | 否 |
| 适合 2C2G 服务器 | ✗ | ✗ | ✓ |
服务器目录结构
在讲具体脚本之前,先交代一下服务器上的目录规划。理解这个结构,后面的脚本你一眼就能看明白。
/opt/docker/
├── projects/ # 所有项目的部署目录
│ ├── relax-web/ # 后端项目(Spring Boot)
│ │ ├── relax-web.jar # 应用 jar 包(部署后自动清除)
│ │ ├── Dockerfile # 镜像构建定义
│ │ ├── start.sh # Java 启动脚本
│ │ ├── deploy.conf # 额外 docker run 参数
│ │ ├── .env # 环境变量(可选)
│ │ ├── logs/ # 日志目录(挂载到容器外)
│ │ └── conf/ # Spring 配置文件
│ │ ├── application.yml
│ │ ├── application-prod.yml
│ │ └── dualai-config-prod.properties
│ ├── bookmark_box/ # 前端项目(静态站点)
│ │ └── dist/ # 构建产物
│ └── ... # 其他项目
├── nginx/
│ ├── html/ # Nginx 静态文件根目录
│ │ ├── bookmark_box/ # 前端项目部署后的位置
│ │ └── ...
│ └── conf/
│ └── nginx.conf # Nginx 配置
└── deploy.sh # 统一部署脚本设计思路
- projects 目录集中管理:所有项目统一放在
/opt/docker/projects/下,一个目录就是一个项目,清晰不混乱 - 日志外挂:后端项目的日志通过 Docker volume 挂载到宿主机,容器重启日志不丢失
- 配置外挂:Spring 的配置文件也通过 volume 挂载,修改配置不用重新构建镜像,重启容器即可生效
- 前端直接落地:前端构建产物直接放到 Nginx 的 html 目录下,不走 Docker(静态文件没必要套一层容器)
📷 图片位(待补充)
应放什么图:服务器实际目录结构的 tree 命令输出截图,让读者看到真实的目录布局。
小结
这篇文章聊了整个部署方案的选择过程,核心教训就三条:
- 低配服务器不要在本地搞构建 —— 构建是 CPU/IO 密集型操作,把服务器搞崩是分分钟的事
- CI/CD 不是越复杂越好 —— Jenkins 和 Drone 都很优秀,但对个人项目 + 低配服务器来说就是杀鸡用牛刀
- 简单直接才是最优解 —— Cloud Toolkit(或手动 SCP)+ 统一部署脚本,零额外开销,够用了
下一篇 前后端部署实战:Docker 容器化与脚本设计,会把每个部署文件掰开了讲——Dockerfile 怎么写、启动脚本怎么设计、配置怎么管理、前端后端怎么一步步部署起来。