对于大多数 Django 项目,推荐使用 Jenkins Declarative Pipeline 配合 SSH 插件将代码同步到测试服务器,并在远程执行迁移和静态文件收集命令,适合需要频繁迭代且希望减少人工操作失误的团队。
先说结论:通过 Jenkins 流水线调用 SSH 命令远程部署是测试环境最稳妥的方案,但必须增加数据库备份和敏感配置管理环节,既能保证环境一致性,又能防止数据丢失和配置泄露。
- 适合:拥有独立测试服务器、希望标准化发布流程的 Django 项目。
- 先准备:配置 SSH 密钥凭证,配置部署用户 sudo 免密,确保.env 文件不随代码覆盖。
- 验收:部署完成后检查 Django 日志无报错,页面静态资源加载正常,且数据库备份文件已生成。
核心流水线代码
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sshagent(['test-server-ssh-key']) {
sh '''
ssh user@test-server "
cd /path/to/project &&
source venv/bin/activate &&
git pull &&
# 备份数据库以防迁移失败
python manage.py dumpdata `--exclude-contenttypes` `--exclude-auth`.permission `--exclude-sessions` > backup_$(date +%F).json &&
pip install -r requirements.txt &&
python manage.py migrate &&
python manage.py collectstatic `--noinput` &&
# 修正静态文件权限,避免 403
sudo chown -R www-data:www-data /path/to/project/staticfiles &&
# 重启服务 (需配置 sudo 免密)
sudo systemctl restart gunicorn
"
'''
}
}
}
}
}前置准备与安全配置
1. 配置 SSH 凭证
在 Jenkins 凭证管理中添加"SSH Username with private key",ID 设为test-server-ssh-key,填入私钥内容。
2. 配置 Sudo 免密 (关键)
流水线中的systemctl和chown需要 sudo 权限。登录测试服务器,运行sudo visudo,添加以下行允许部署用户免密执行特定命令,避免流水线卡住:deploy_user ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/chown
3. 敏感配置管理
不要将.env或包含SECRET_KEY的文件提交到 Git。确保测试服务器上已存在该文件,并在.gitignore中忽略。若需更新环境变量,建议通过 Jenkins 凭证注入或在流水线中使用scp单独同步配置文件,而非git pull覆盖。
部署验证
部署完成后,不要只看 Jenkins 显示“成功”,需要进一步确认:
1. 检查服务状态:运行systemctl status gunicorn,确认服务处于 active (running) 状态。
2. 检查静态文件:访问测试服务器域名,查看页面 CSS 和 JS 是否加载正常,排查 403 错误。
3. 查看应用日志:查看 Django 或 Gunicorn 的日志文件,确认没有 ImportError 或 Database 连接错误。
4. 确认备份生成:检查项目目录下是否生成了新的backup_*.json文件。
常见坑与排查
1. 虚拟环境路径错误
远程执行命令时,Shell 可能不加载用户的.bashrc。建议在命令中写绝对路径,如/path/to/venv/bin/python,或者显式 source 激活脚本。
2. 静态文件权限问题collectstatic生成的文件归属可能是 Jenkins 用户,而 Web 服务器(如 Nginx)通常由 www-data 运行。务必执行sudo chown -R www-data:www-data /path/to/project/staticfiles,否则页面会报 403 错误。
3. 迁移导致数据丢失
执行migrate前务必备份。若迁移失败,可使用备份文件还原:python manage.py loaddata backup_*.json。
4. 测试环境 DEBUG 未关闭
确保测试服务器的settings.py或环境变量中DEBUG设置符合预期。虽然测试环境可以开启 DEBUG 以便排查,但要注意不要泄露敏感信息,且需配置正确的ALLOWED_HOSTS。
参考来源
- Jenkins 官方文档,Pipeline 语法参考,https://www.jenkins.io/doc/book/pipeline/syntax/
- Django 官方文档,How to deploy with WSGI,https://docs.djangoproject.com/en/stable/howto/deployment/wsgi/