自动部署脚本如何写?

wen 实用脚本 70

自动部署脚本如何写?从零构建高效CI/CD流水线实战指南

目录导读

  1. 为什么需要自动部署脚本? – 核心价值与场景解析
  2. 自动部署脚本的核心组件 – 必备模块与设计原则
  3. 实战:编写一个生产级部署脚本(Shell + Docker)
  4. 常见问题问答 – 开发者高频困惑与解决方案
  5. 进阶技巧 – 安全加固、回滚策略与监控集成

为什么需要自动部署脚本?

价值定位

手动部署耗时易错,尤其在微服务架构、多环境(开发/测试/生产)切换时,自动部署脚本能实现一键构建→测试→部署→回滚,将发布周期从小时级压缩至分钟级,根据DORA报告,高效部署团队比低效团队部署频率高200倍,故障恢复快24倍。

自动部署脚本如何写?

适用场景

  • 前端项目(React/Vue)构建后部署至Nginx/CDN
  • 后端服务(Java/Node.js/Python)打包后部署至服务器集群
  • 容器化应用(Docker镜像构建→推送→Kubernetes更新)

自动部署脚本的核心组件

一个完整的部署脚本应包含以下模块:

# 伪代码结构示意
deploy.sh  
├── 环境检测(检查依赖工具、变量是否存在)  
├── 代码拉取(从Git拉取指定分支/标签)  
├── 构建阶段(编译、打包、生成制品)  
├── 测试阶段(单元测试、静态检查、集成测试)  
├── 部署阶段(推送至服务器/容器仓库/云平台)  
├── 健康检查(验证服务是否正常启动)  
└── 回滚预案(失败时自动切换至前一版本)  

设计原则:幂等性(重复执行结果一致)、可配置性(通过环境变量控制)、原子性(要么全成功,要么全失败回滚)。


实战:编写一个生产级部署脚本

场景:Node.js后端服务(使用Docker部署至Linux服务器)

Step 1: 基础环境变量

创建deploy.env文件,不包含敏感信息到代码库:

PROJECT_NAME=my-api  
GIT_REPO=https://github.com/company/my-api.git  
DEPLOY_BRANCH=main  
DOCKER_IMAGE_TAG=my-api:v1.0.0  
REMOTE_SERVER=user@your-server.com  
REMOTE_DEPLOY_DIR=/opt/apps/my-api  
HEALTH_CHECK_URL=http://your-server.com:3000/health  
Step 2: 主脚本deploy.sh
#!/bin/bash  
set -euo pipefail  # 严格模式:任何错误立即退出  
# 1. 加载配置  
source deploy.env  
echo "[INFO] 开始自动部署: $PROJECT_NAME"
# 2. 克隆/更新代码  
if [ -d "repo" ]; then  
  cd repo && git pull origin $DEPLOY_BRANCH  
else  
  git clone -b $DEPLOY_BRANCH $GIT_REPO repo  
  cd repo  
fi  
echo "[OK] 代码拉取完成"
# 3. 构建Docker镜像  
docker build -t $DOCKER_IMAGE_TAG .  
echo "[OK] 镜像构建完成"
# 4. 推送镜像到私有仓库(可选)  
# docker push $DOCKER_REGISTRY/$DOCKER_IMAGE_TAG  
# 5. 远程部署(通过SSH)  
ssh $REMOTE_SERVER << EOF  
  set -e  
  echo "--- 远程部署开始 ---"  
  # 停止旧容器(等待10秒超时)  
  docker stop $PROJECT_NAME || true  
  docker rm $PROJECT_NAME || true  
  # 启动新容器(映射端口、挂载卷、设置环境变量)  
  docker run -d \  
    --name $PROJECT_NAME \  
    -p 3000:3000 \  
    -v /data/logs:/app/logs \  
    -e NODE_ENV=production \  
    --restart=always \  
    $DOCKER_IMAGE_TAG  
  echo "--- 远程部署完成 ---"  
EOF  
# 6. 健康检查(重试5次,间隔5秒)  
for i in {1..5}; do  
  if curl -f -s -o /dev/null "$HEALTH_CHECK_URL"; then  
    echo "[OK] 健康检查通过,部署成功!"  
    exit 0  
  fi  
  echo "[WARN] 等待服务启动... ($i/5)"  
  sleep 5  
done  
# 7. 失败回滚  
echo "[ERROR] 健康检查失败,触发回滚..."  
ssh $REMOTE_SERVER "docker stop $PROJECT_NAME && docker rm $PROJECT_NAME && docker run -d --name $PROJECT_NAME -p 3000:3000 $PREVIOUS_TAG"  
exit 1  
Step 3: 本地执行与CI集成
  • 本地测试:bash deploy.sh
  • 集成到GitHub Actions(.github/workflows/deploy.yml片段):
    jobs:  
    deploy:  
      runs-on: ubuntu-latest  
      steps:  
        - uses: actions/checkout@v3  
        - name: Run deploy script  
          env:  
            SSH_PRIVATE_KEY: ${{secrets.SSH_KEY}}  
          run: |  
            echo "$SSH_PRIVATE_KEY" > ssh_key  
            chmod 600 ssh_key  
            bash deploy.sh  

常见问题问答

Q1:部署脚本中如何安全处理密码/API密钥?
A:绝对不要硬编码在script中!使用环境变量(从CI平台的Secrets管理读取),或者采用Hashicorp Vault等密钥管理服务,示例:export DB_PASSWORD=${SECRET_DB_PASSWORD}

Q2:部署中途失败,如何避免服务完全不可用?
A:采用蓝绿部署滚动更新策略,在脚本中添加“启动新容器后保留旧容器”,健康检查失败时立即切换回旧版本,也可使用Kubernetes的RollingUpdate自动完成。

Q3:windows平台如何实现自动部署?
A:考虑使用PowerShell脚本(.ps1)或WSL(Windows Subsystem for Linux),如果团队混合使用,可以选择跨平台的Ansible(YAML语法)或Pulumi(TypeScript)。

Q4:脚本如何支持多环境(dev/staging/prod)?
A:通过传递环境参数:bash deploy.sh production,脚本内部根据参数加载不同配置:

case "$1" in  
  dev)  
    source deploy-dev.env  
    ;;  
  prod)  
    source deploy-prod.env  
    ;;  
esac  

Q5:是否需要为每个项目写独立脚本?
A:推荐封装通用函数库,形成部署模板,例如将“拉代码→构建→测试→部署”抽象为函数,不同项目只需修改配置文件和构建参数,开源方案:GitLab CI模板库、Jenkins Shared Libraries。


进阶技巧与最佳实践

安全加固

  • SSH免密登录:部署服务器使用ssh-keygen生成密钥对,把公钥加入~/.ssh/authorized_keys,私钥通过环境变量传入。
  • 最小权限原则:部署脚本使用的SSH用户只拥有部署目录的读写权限,及Docker容器管理权限,不给予sudo权限。

回滚策略

除了脚本内的紧急回滚,建议保留最近5个可用版本标签:

docker tag my-api:v1.0.0 my-api:latest  
docker push my-api:v1.0.0  # 同时保留历史版本  

回滚时只需:docker run my-api:v0.9.0

监控集成

在健康检查后追加告警通知

if [ $? -eq 0 ]; then  
  curl -X POST -H "Content-Type: application/json" \  
    -d '{"text":"部署成功: '$PROJECT_NAME'"}' \  
    https://hooks.slack.com/services/YOUR_WEBHOOK  
fi  

性能优化

  • 使用缓存层:Docker构建时合理利用缓存层(先复制package.json安装依赖,再复制源代码)
  • 并行部署:对于多台服务器,使用psshAnsibleserial参数并行执行SSH命令,将部署时间从N*time降低为time

通过以上实践,你的自动部署脚本将具备生产级可靠性。好的脚本是自我文档化的,添加清晰的日志输出(使用[INFO] [WARN] [ERROR]前缀),让每次部署都像一本可读的操作手册,当团队内新成员也能轻松通过执行一条命令完成上线时,你的自动化就成功了。

抱歉,评论功能暂时关闭!