我的完整开发部署工作流:从本地到VPS的自动化实战指南
结论先行:独立开发者最该自动化的就是一件事:把「本地 Docker Compose 写代码 →
git push→ GitHub Actions 自动测试、构建镜像、部署到 VPS → Telegram 通知」这条路打通。我的实测是单次部署从 18 分钟压到 4 分钟,凌晨困到手滑也不会把线上搞挂。一台 VPS、一个中小项目,照这套搭两天能跑通。但如果你是纯前端或 Serverless 项目,先用 Vercel / Cloudflare Pages 这类零运维托管,需要长驻后端进程时再上 VPS。
昨天改了8次代码,每次都要SSH登录服务器、git pull、重启服务。凌晨1点最后一次部署时,脑子已经糊了,漏看了报错日志,导致线上服务挂了半小时。这事儿不能这么下去了。
0、写在前面
之前我的开发流程是这样的:
- 改代码
- 本地测试
git push- SSH 登录服务器
git pull- 重启服务
- 手动验证
看似简单,但一天改个十几次代码,光 SSH 登录服务器、敲命令就要花掉不少时间。更糟的是,容易出错,忘记 pull、重启错了服务、漏看了报错日志。
后来我花了两天时间,把这套流程自动化了。现在只需要:
1 | git add . |
三分钟后,生产环境自动更新完成,Telegram 还会收到部署通知。
这篇文章就把这套工作流完整分享给你,从零开始搭建,照做就能用。
0.1 前置知识检查
开始前,问自己这几个问题:
- ✅ 我用过Git吗?(基本的add/commit/push)
- ✅ 我有VPS吗?(如果没有,推荐Vultr注册一个)
- ✅ 我了解Docker基本概念吗?(镜像、容器、Dockerfile)
- ✅ 我的代码能本地跑起来吗?
如果上面有❌,不要着急!先花1-2小时补一下对应知识。
1、期望目标
搭建一套「从代码到生产」的完整自动化流程:
写完代码,git push,3分钟后自动上线。这套自动化流程包含:
- ✅ 本地开发:Docker Compose 一键启动开发环境
- ✅ 代码管理:Git 规范化提交,自动检查代码质量
- ✅ 自动化测试:push 时自动跑测试
- ✅ 自动构建:构建 Docker 镜像并推送到镜像仓库
- ✅ 自动部署:rsync 同步文件到 VPS,重启服务
- ✅ 部署通知:Telegram / Discord / Slack 通知部署结果
- ✅ 回滚能力:出问题时快速回滚到上一个版本
我的实测:单次部署从18分钟降到4分钟(后面有对比表),两个月零部署事故。
2、计划思考
为什么需要标准化工作流?
独立开发者的时间很贵,不应该浪费在重复劳动上。但很多人(包括以前的我)觉得:
「我的项目很小,手动部署也很快啊,搞自动化是不是浪费时间?」
这是个陷阱。项目小的时候确实手动部署不麻烦,但问题是:
| 场景 | 手动部署的问题 | 自动化部署的优势 |
|---|---|---|
| 频繁迭代 | 每次都要重复操作,容易出错 | push 就完事,零心智负担 |
| 多环境(开发/测试/生产) | 容易混淆环境,把测试代码上到生产 | 自动区分环境,绝不可能搞错 |
| 团队协作 | 其他人不知道怎么部署 | 文档即代码,workflow 就是文档 |
| 凌晨 2 点修 bug | 困倦时容易手滑,删库跑路 | 自动化流程固定,不会犯错 |
| 多个项目 | 每个项目部署方式不同,记忆负担大 | 统一模板,新项目 5 分钟配好 |
| 出问题要快速回滚 | 手动回滚容易漏步骤 | 一个命令回滚,从容应对 |
自动化工作流这把效率武器,独立开发者比大公司更需要。
工具选型
| 类别 | 工具 | 为什么独立开发者需要它 | 新手可以跳过吗 |
|---|---|---|---|
| 代码仓库 | GitHub | 免费私有仓库 + Actions CI/CD 太好用 | ❌ 必备 |
| 容器化 | Docker | 环境一致性,部署不依赖本地环境 | ❌ 必备 |
| CI/CD | GitHub Actions | 和代码仓库无缝集成,免费额度够用 | ❌ 必备 |
| 镜像仓库 | Docker Hub | 官方仓库,免费私有仓库 | ❌ 必备 |
| VPS | 任意云厂商 | 我常用 Vultr 和 DigitalOcean | ❌ 必备 |
| 反向代理 | Nginx | 稳定、功能强大、社区活跃 | ✅ 可选(Caddy更简单) |
| 进程管理 | Docker Compose | 管理多容器很方便 | ❌ 必备 |
💡 出海开发者福利
Vultr 和 DigitalOcean 都有全球机房,离用户越近延迟越低。我用这两家多年,稳定、性价比高,不用实名备案(国内开发者都懂这里的繁琐与卡点)。注册时通过我的 aff 链接,还能拿新用户优惠。
3、操作步骤
3.1 本地开发环境配置
安装必要工具
确保本地装了这些工具(Mac 用 Homebrew,Linux 用 apt/yum,Windows 用 WSL2):
1 | # Mac(新版Docker Desktop) |
⚠️ Windows 用户
强烈建议用 WSL2 跑 Docker Desktop,不要用原生 Windows Docker。性能、兼容性都好太多。
项目结构示例
一个典型的项目结构:
1 | my-project/ |
创建 Dockerfile
1 | # 多阶段构建:先构建,再打包成运行时镜像 |
💡 多阶段构建的好处
- 最终镜像只包含运行时文件,体积小(从 500MB 降到 50MB 很常见)
- 不包含构建工具(gcc、make 等),安全性更高
- 拉取镜像更快,部署更快
本地开发用 docker-compose.yml
1 | services: |
启动开发环境:
1 | # 一键启动 |
3.2 Git 工作流规范
.gitignore 配置
不要把敏感文件、依赖文件提交到仓库:
1 | # .gitignore |
💡 永远不要提交 .env!
.env里通常有数据库密码、API Key 等敏感信息。一旦泄露到 GitHub,就是灾难。正确做法:提交
.env.example(示例文件),生产环境变量在 VPS 上配置。
规范化提交信息(可选,团队协作时推荐)
如果你是独立开发者,基本的 git commit 就够了。如果是团队协作,可以安装 commitizen 工具:
1 | # 全局安装 |
会引导你选择提交类型:
1 | ? Select the type of change that you're committing: |
然后让你输入描述,自动生成规范的提交信息:
1 | feat: add user authentication feature |
这样做的价值:
- 看 git log 就知道项目做了什么:
git log --oneline - 自动生成 Changelog:可以用 standard-version 自动生成版本日志
- 自动化版本管理:语义化版本号(Semantic Versioning)
Pre-commit 钩子(可选,团队协作时推荐)
独立开发时手动跑 lint 也够了。团队协作时,用 husky 在提交前自动检查代码:
1 | # 安装 |
配置 package.json:
1 | { |
现在每次提交会自动:
- 跑 ESLint 检查代码质量
- 跑 Prettier 格式化代码
- 只检查暂存的文件(lint-staged)
3.3 GitHub Actions CI/CD
创建 workflow 文件
创建 .github/workflows/deploy.yml:
1 | name: Deploy to VPS |
配置 GitHub Secrets
在 GitHub 仓库设置里添加这些 Secrets(Settings → Secrets and variables → Actions):
| Secret 名称 | 说明 | 获取方式 |
|---|---|---|
| Secret 名称 | 说明 | 获取方式 |
| ---------------- | ---------------------------- | -------------------------------- |
DOCKER_USERNAME |
Docker Hub 用户名 | 你的 Docker Hub 账号 |
DOCKER_PASSWORD |
Docker Hub 密码/Access Token | Docker Hub 设置 |
VPS_HOST |
VPS 的 IP 地址或域名 | 你的 VPS IP |
VPS_USER |
VPS 登录用户名(非root) | 之前创建的部署用户(如 deploy) |
SSH_PRIVATE_KEY |
SSH 私钥 | 在本地生成,见下文 |
TELEGRAM_BOT_TOKEN |
Telegram Bot Token | 找 @BotFather 获取 |
TELEGRAM_CHAT_ID |
接收通知的 Chat ID | 见下文 |
生成部署用 SSH 密钥
🛠️ 一键 SSH 密钥与免密配置:
如果觉得手动配置 ED25519 密钥、修改authorized_keys权限容易出错,推荐使用ittinker-scripts开源的ssh-key-setup自动化脚本快速完成基线配置:
1 curl -sSL https://raw.githubusercontent.com/ittinker/ittinker-scripts/main/ssh-key-setup/setup.sh | bash
手动生成步骤如下:
1 | # 在本地生成部署专用密钥对 |
把公钥添加到 VPS:
1 | # 在 VPS 上,把公钥添加到部署用户的 authorized_keys |
把私钥内容复制到 GitHub Secrets SSH_PRIVATE_KEY:
1 | # 复制私钥(包含 BEGIN 和 END 行) |
配置部署通知
Telegram Bot:
- 找 @BotFather 创建 Bot,获取 Token
- 把 Bot 拉入你的频道/群组
- 获取Chat ID(注意顺序!)
- 先给你的Bot发任意消息(如"/start")
- 然后访问这个URL:
1
curl https://api.telegram.org/bot<TOKEN>/getUpdates
- 返回JSON里找到
message.chat.id(或result[0].message.chat.id)- 个人聊天:正数ID
- 群组/频道:负数ID(通常是-100xxxxxx)
- ⚠️ 常见错误:直接访问URL没给Bot发消息,返回空结果
- 在 workflow 里用 curl 发通知:
1 | - name: Notify on Telegram |
3.4 VPS 部署配置
💡 还没VPS?Vultr/DigitalOcean注册时通过我的aff链接,还能拿新用户优惠
创建部署用户
不要用 root 部署,创建专用用户:
1 | # 在 VPS 上 |
生产环境 docker-compose.prod.yml
1 | services: |
Nginx 反向代理
编写 nginx.conf:
1 | events { |
环境变量管理
创建 .env 文件(不要提交到 git):
1 | # 1. SSH登录VPS并进入项目目录 |
SSL 证书(Let’s Encrypt)
用 certbot 获取免费 SSL 证书:
1 | # 安装 certbot |
3.5 监控与日志
日志管理
查看容器日志:
1 | # 查看所有日志 |
日志轮转(在 docker-compose.yml 里配置):
1 | logging: |
健康检查
在 Dockerfile 里定义健康检查(前面已有),检查状态:
1 | # 查看容器健康状态 |
监控告警
用 Uptime Kuma 监控服务可用性:
1 | docker run -d --restart=always \ |
访问 http://<你的VPS-IP>:3001,配置监控:
- 添加监控端点(如
https://example.com/api/health) - 设置告警(Telegram/邮件/Discord)
- 配置检查间隔(1-5 分钟)
🛠️ VPS 宿主机资源水位监控:
除了用 Uptime Kuma 探测 HTTP 业务可用性,VPS 本身的 CPU、内存和磁盘水位也需要守护。推荐在服务器部署ittinker-scripts开源的vps-health-monitor,当磁盘或内存占用超 85% 时自动通过 Telegram 推送报警:
1 curl -sSL https://raw.githubusercontent.com/ittinker/ittinker-scripts/main/vps-health-monitor/install.sh | bash
3.6 回滚策略
当新版本出问题,快速回滚:
1 | # 方法1:回滚到上一个镜像 |
更好的做法:保留最近几个版本的镜像:
1 | # 在 workflow 里,不要删除旧镜像 |
4、总结
检查清单
上线前检查这些:
| 检查项 | 命令/方法 | 预期结果 |
|---|---|---|
| 本地测试通过 | docker compose up -d && 测试 |
所有功能正常 |
| 测试通过 | npm test |
无失败用例 |
| 代码检查通过 | npm run lint |
无报错 |
| Docker 镜像构建成功 | docker build -t test . |
构建成功 |
| GitHub Actions 通过 | 查看 Actions 标签页 | 绿色 ✅ |
| VPS 能拉取镜像 | SSH 到 VPS: docker pull <image> |
拉取成功 |
| 环境变量已配置 | cat .env |
所有必需变量都有 |
| SSL 证书有效 | curl -I https://example.com |
返回 200/301 |
| 健康检查通过 | docker ps |
状态为 healthy |
| 监控已配置 | Uptime Kuma/其他工具 | 监控端点已添加 |
关键文件位置
1 | GitHub 仓库: |
效率提升
| 操作 | 手动部署耗时 | 自动化部署耗时 | 节省时间 |
|---|---|---|---|
| 提交代码 | 1 分钟 | 1 分钟 | 0 |
| 登录服务器、拉取代码 | 2 分钟 | 0 | 2 分钟 |
| 重启服务、验证 | 5 分钟 | 3 分钟 | 2 分钟 |
| 修复遗漏的问题 | 10 分钟 | 0 | 10 分钟 |
| 合计 | 18 分钟 | 4 分钟 | 77% |
最佳实践
- 小步快跑:频繁提交小改动,而不是攒一大堆再发
- 自动化一切:手动做的事超过 3 次,就该自动化
- 监控先行:先配监控,再上线,出问题才能第一时间知道
- 保留回滚能力:永远保持能快速回退到上一个稳定版本
- 文档即代码:workflow 文件就是最好的部署文档
5、异常记录
Q1:GitHub Actions 拉取私有子模块失败?
现象:
1 | fatal: clone of '[email protected]:private/repo.git' failed |
解决方案:
在 workflow 里添加 SSH key 配置:
1 | - name: Setup SSH |
Q2:Docker 构建太慢?
优化方法:
- 利用层缓存:把变化少的指令放前面
1 | # ✅ 好:利用缓存 |
- 用 BuildKit 缓存挂载:
1 | DOCKER_BUILDKIT=1 docker build --cache-from=my-app:latest . |
- GitHub Actions 缓存:
1 | - name: Cache Docker layers |
Q3:部署后网站 502 Bad Gateway?
排查步骤:
- 容器是否在运行:
1 | docker ps |
- 查看日志:
1 | docker compose logs app |
- 检查环境变量:
1 | docker compose exec app env | grep DB |
- 手动测试容器:
1 | docker compose exec app curl http://localhost:3000 |
常见原因:
- 环境变量没配置
- 数据库连接失败
- 端口冲突
- 启动超时(增加
healthcheck的start_period)
Q4:rsync 同步太慢或卡住?
优化方法:
- 排除不必要的文件:
1 | switches: -avzr --delete \ |
-
用压缩(-z 已启用):网络慢时特别有用
-
检查 SSH 密钥性能:ED25519 比 RSA 快
-
换 rsync 镜像:用国内镜像加速 GitHub Actions 的 rsync
Q5:Docker 镜像太大,部署慢?
优化方法:
- 用 alpine 基础镜像:
1 | FROM node:22-alpine # 100MB |
-
多阶段构建:前面已讲
-
合并 RUN 指令:
1 | # ✅ 好:一层 |
- 清理缓存:
1 | RUN npm ci && \ |
Q6:Let’s Encrypt 证书申请失败?
常见原因:
-
域名还没解析到 VPS:先等 DNS 生效(用
dig example.com检查) -
80 端口被占用:确保 Nginx 没在运行,或者用 standalone 模式
-
申请次数超限:Let’s Encrypt 有速率限制,不要频繁申请
解决方案:用 DNS 验证(不受端口限制)
1 | sudo certbot certonly --manual --preferred-challenges dns -d example.com |
Q7:内存不够用,容器被杀?
现象:
1 | docker ps # 容器消失 |
解决方案:
- 限制容器内存:
1 | services: |
- 加 Swap:
1 | # 创建 2GB swap |
- 升级 VPS:如果是长期项目,建议至少 1GB 内存(可以用 Vultr 的高内存实例)
6、FAQ(独立开发者最常问的 5 个问题)
Q1:项目还在早期,一定要上全套 CI/CD 吗?什么时候开始自动化?
不用一上来就全上。MVP 阶段一天改不了几次代码,手动部署完全够。但只要出现下面任一信号,就该至少把「push → 自动构建 → 部署」这条主干自动化:
- 同一天部署超过 3 次
- 已经有真实用户在用,凌晨翻车会丢用户
- 部署步骤多到要照着备忘录敲
监控(Uptime Kuma)要早于花哨的 CI 配齐,上线第一天就该有,否则出问题你最后一个知道。
Q2:GitHub Actions 免费额度够用吗?私有仓库要不要花钱?
够。免费账户私有仓库每月 2,000 分钟,公共仓库无限免费。一个中小项目单次 CI 大概 5-10 分钟,一个月几十次部署远用不完。要留意两点:ubuntu runner 按 1 倍计费,macOS runner 按 10 倍计费(独立开发者基本只用 ubuntu);以及从 2026 年 3 月 1 日起,私有仓库跑自托管 runner 收 $0.002/分钟的"平台费",GitHub 把它算进你的免费分钟额度里抵扣(按 list price 计)。GitHub 托管 runner 不收平台费(仍走免费 2,000 分钟/月);公共仓库完全免费,包括自托管 runner。
Q3:镜像仓库选 Docker Hub 还是 GitHub Container Registry?
独立开发者建议直接用 GitHub Container Registry(ghcr.io)。它目前存储和流量都免费,公共、私有镜像拉取都没有限速;而 Docker Hub 免费账户每 6 小时只给 200 次匿名拉取,生产环境多拉几次就撞限。GHCR 还有个隐形好处:在 Actions 里用内置的 GITHUB_TOKEN 就能登录推送,不用再去 Docker Hub 建账号、往 Secrets 里存一份密码。
Q4:docker-compose 和 docker compose,到底用哪个?
用 docker compose(中间是空格)。这是 V2,用 Go 写的,随 Docker Desktop 自带,是当前主推版本。docker-compose(连字符)是 V1,Python 写的,2023 年 6 月已停止维护。多数机器上两个命令都能跑,因为 V2 提供了兼容别名,但新项目一律写 V2。另外,新写的 docker-compose.yml 也不需要再写 version: '3.8' 这一行,Compose 规范已把它标为废弃,写了也会被忽略并告警。
Q5:没有 VPS,能直接用 Vercel / Cloudflare Pages 这类托管吗?
能,而且建议先试。纯前端或 Serverless 全栈(Next.js、Remix 等)直接上 Vercel / Cloudflare Pages,零运维、免费额度够 MVP,git push 就上线,连这套 CI/CD 都不用自己搭。只有当你需要长驻进程时才该上 VPS:定时任务、WebSocket、爬虫、数据库长连接、自定义系统服务,或者后端跑得多、PaaS 按量计费比 VPS 还贵的时候。
下一篇预告
下一篇我们来讲 容器化最佳实践,会更深入地介绍:
- 如何设计高效的 Dockerfile
- Docker Compose 高级配置
- 容器安全加固
- 多容器编排技巧
- 多环境部署(适合团队协作项目)
这套工作流我已经用了两年多,支撑了多个项目从 0 到 1 再到稳定盈利。独立开发者的时间很贵,把重复劳动自动化,才能把精力用在真正重要的事情上,打磨产品、服务用户、探索新可能。
独立开发者工具箱系列,欢迎关注!
💡 透明声明:本文包含 5 处推广链接(2 个独立服务,如 Vultr / Cloudflare / Tailscale 等)。每次点击我会收到一笔佣金,不影响你的购买价格,也不影响我的内容判断,工具好不好用我自己用了才知道。完整推广政策见 ittinker.com/about。
数据与引用
-
GitHub Actions 2026 年免费政策(2026 年 3 月起):私有仓库免费档仍是 2,000 Linux 分钟/月 + 500 MB 制品存储;2026 年 3 月 1 日起,新增 $0.002/分钟的"平台费",并把自托管 runner 也纳入免费分钟池,意味着公共仓库仍然完全免费(hosted runner 不收费),私有仓库存量自托管 runner 也开始按 list price 抵扣免费额度。
来源:GitHub Actions 2026 定价更新,GitHub Changelog 2025-12-16
含义:独立开发者用公共仓库存代码、迁移到 GHCR 的玩法不受影响;如果你的项目是私有仓 + 大量自托管 runner 做构建,从 2026 年 3 月起可能要付一点平台费(多数个人项目仍吃不完免费额度)。 -
GitHub Actions 2026 年 1 月降价:hosted runner 单价在 1 月 1 日已下调最高 39%,Linux 2 核从 $0.008/分钟降到 $0.006,Windows 从 $0.016 降到 $0.010,macOS 从 $0.080 降到 $0.062。
来源:Is GitHub Actions Free in 2026,CICDCalculator.com
含义:即使你不小心跑超免费额度,超额成本比 2025 年便宜约 1/3;多数小型项目跑不超免费层不用 care。 -
GitHub Octoverse 2025 全球开发者大盘:平台 2025 年新增 3,600 万开发者,总用户 1.8 亿+;merge 了 5.187 亿 PR(+29% YoY),9.86 亿次 commit(+25% YoY)。
来源:GitHub Octoverse 2025,Forbes 摘要
含义:CI/CD 工作流从"加分项"变成"基础设施",你搭这套自动化不是过度工程,是在跟进主流玩家都在做的事。 -
GitHub Actions Marketplace 规模:2025 年时收录的官方/社区 Actions 已超 20,000 个,每月跑约 2.63 亿 jobs,单日算力 4,100 万+ build hours,容器化 workflow 同比 +25%。
来源:GitHub statistics 2025,TMS Outsource
含义:绝大多数需要的步骤(缓存、Lint、推送镜像、SSH 部署、发 Telegram 通知)都有现成 Action,文章里那几行uses: actions/...是踩了全社区验证过的轮子。 -
Docker Compose V1 → V2 迁移:
docker-compose(连字符)是 Python 写的 V1,2023 年 6 月已停止维护;docker compose(空格)是 V2,Go 写的,随 Docker Desktop 内置分发,是当前主推。多数机器 V2 提供兼容别名所以两个命令都能跑。
来源:Docker Compose V2 GA,Docker 官方博客
含义:文章里写的docker compose up -d还能跑,但你手写新脚本、装新机器时一律用 V2,避免装老镜像踩维护终止的坑。新版docker-compose.yml顶部那行version: '3.8'也已经不需要写了(Compose 规范已标废弃)。 -
本机 Docker 镜像变小技巧的实际收益:多阶段构建 +
node:22-alpine基础镜像,能把 Node.js 镜像从约 900 MB 压到约 100 MB;拉镜像时间、磁盘占用、构建缓存体积同比例下降。
来源:Docker Hub,node 镜像标签页
含义:这是 FAQ Q4 之外另一个"日常肉眼可见"的优化,COLD 部署从 5 分钟降到 30 秒,长任务挂着不被网络抖动拖垮。 -
VPS 商家定价(2026 年 4 月):Hetzner 4 月 1 日起 CX/CAX 系列涨 33-38%(DRAM/NVMe 成本,对老客户也生效)但 20 TB/月带宽仍是三家最宽松;DigitalOcean、Vultr 同等配置 $12-24/月。
来源:DigitalOcean vs Vultr vs Hetzner 2026,BitDoze
含义:CI/CD 流水线把 VPS 部署从"手工运维"变成"自动恢复",同等 $12/月 的内存/带宽/IO 差距就是从"勉强支撑"到"从容应对并发"的差距。 -
VPS 商家定价(2026 年 4 月):Hetzner 4 月 1 日起 CX/CAX 系列涨 33-38%(DRAM/NVMe 成本,对老客户也生效)但 20 TB/月带宽仍是三家最宽松;DigitalOcean、Vultr 同等配置 $12-24/月。
来源:DigitalOcean vs Vultr vs Hetzner 2026,BitDoze
含义:CI/CD 流水线把 VPS 部署从"手工运维"变成"自动恢复",同等 $12/月 的内存/带宽/IO 差距就是从"勉强支撑"到"从容应对并发"的差距。