标准部署流程
如果你的部署依赖"手感"和"记忆",那它迟早会在忙的时候出错。
最小部署流程
graph TD
A[拉代码/制品] --> B[备份当前版本]
B --> C[安装依赖/编译]
C --> D[数据库迁移]
D --> E[切换软链接 + 重启服务]
E --> F{健康检查通过?}
F -->|是| G[部署成功 ✅]
F -->|否| H[回滚到旧版本]
H --> I[告警通知]
完整部署脚本(可直接使用)
#!/usr/bin/env bash
set -euo pipefail
# === 配置 ===
APP_DIR=/opt/myapp
REPO_URL=https://github.com/example/myapp.git
TAG=${1:-main} # 用法: ./deploy.sh v1.2.3
RELEASE_DIR=$APP_DIR/releases/$(date +%Y%m%d-%H%M%S)
HEALTH_URL=http://127.0.0.1:3000/health
LOG=$APP_DIR/deploy.log
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; }
log "=== 开始部署 tag=$TAG ==="
# 1. 备份当前版本(软链接目标)
CURRENT=$(readlink -f $APP_DIR/current 2>/dev/null || echo "")
if [[ -n "$CURRENT" ]]; then
cp -r "$CURRENT" "$APP_DIR/backup-$(date +%Y%m%d-%H%M%S)"
log "备份完成: $CURRENT"
fi
# 2. 拉取新版本
git clone --depth 1 --branch "$TAG" "$REPO_URL" "$RELEASE_DIR"
log "代码拉取完成: $RELEASE_DIR"
# 3. 安装依赖(Node.js 示例;Python 替换为 pip install -r requirements.txt)
cd "$RELEASE_DIR"
npm ci --production
log "依赖安装完成"
# 4. 数据库迁移(失败则中止,不切换)
npm run db:migrate || {
log "数据库迁移失败,中止部署"
rm -rf "$RELEASE_DIR"
exit 1
}
log "数据库迁移完成"
# 5. 切换软链接 + 重启服务
ln -sfn "$RELEASE_DIR" "$APP_DIR/current"
sudo systemctl restart myapp
log "服务重启完成"
# 6. 健康检查(等 5 秒让服务启动)
sleep 5
if curl -sf "$HEALTH_URL" > /dev/null; then
log "=== 部署成功: $RELEASE_DIR ==="
else
log "健康检查失败,开始回滚..."
PREV_BACKUP=$(ls -td "$APP_DIR"/backup-* 2>/dev/null | head -1)
if [[ -n "$PREV_BACKUP" ]]; then
ln -sfn "$PREV_BACKUP" "$APP_DIR/current"
sudo systemctl restart myapp
log "已回滚到: $PREV_BACKUP"
else
log "无可用备份,手动介入!"
fi
exit 1
fi
# 7. 清理旧 release(保留最近 3 个)
ls -td "$APP_DIR"/releases/*/ | tail -n +4 | xargs rm -rf
log "旧版本清理完成"
部署失败场景速查表
| 症状 | 根因 | 排查命令 |
|---|---|---|
| 健康检查 curl 超时 | 应用启动失败 / 端口未监听 | journalctl -u myapp -n 50 |
| 数据库迁移报错 | 迁移脚本有 bug 或 DB 权限不足 | 查迁移日志,手动回滚 SQL |
systemctl restart 后 failed | ExecStart 路径错误 / 依赖缺失 | systemctl status myapp |
| 回滚后仍报错 | 备份时已损坏,或 DB 迁移不可逆 | 从昨日备份恢复数据库 |
| 新版本启动但功能异常 | 配置未同步(遗漏环境变量) | 对比新旧 .env 文件 |
常见误区
| 误区 | 正确做法 |
|---|---|
"只要 systemctl restart 就算部署了" | restart 只是重启进程,代码和配置是否正确与 restart 无关 |
| "先迁移数据库再部署代码,安全" | 数据库迁移在新代码拉取之后立即执行,若迁移失败则不切换软链接 |
| "备份只需要代码目录" | 代码 + 数据库 dump + 配置文件三者均要备份 |
| "健康检查返回 200 就一定正常" | /health 端点应检查数据库连接,不能只返回硬编码 200 |
本节执行清单
- [ ] 把部署步骤写成固定脚本(参考上方模板)
- [ ] 为脚本增加
set -euo pipefail和trap错误处理 - [ ] 确认迁移失败时脚本能中止而不切换
- [ ] 测试一次故意失败的部署,确认回滚有效
下一节:systemd 托管应用——把部署结果交给可控的服务管理器。