Python
部署 Django 项目
发布于 2026年7月23日
部署 Django 项目
本篇给出一条清晰的生产部署主线:PostgreSQL 保存业务数据,应用服务器运行 Django,Nginx 提供 HTTPS、静态文件和反向代理。不同云平台操作细节不同,但核心职责相同。
一、生产架构
浏览器
-> HTTPS / Nginx 或云负载均衡
-> Gunicorn(WSGI)或 Uvicorn(ASGI)
-> Django
-> PostgreSQL / Redis / 对象存储
- Nginx:TLS、静态资源、请求大小限制和反向代理。
- 应用服务器:管理 Django Worker,不能使用
runserver。 - PostgreSQL:生产业务数据。
- Redis:缓存或任务队列,按项目需要引入。
- 对象存储:持久化用户上传文件,适合多实例部署。
二、冻结依赖
简单项目可使用:
python -m pip freeze > requirements.txt
python -m pip install -r requirements.txt
更成熟的项目可以使用支持锁文件的依赖工具。无论用哪种方式,都应在干净环境验证能够重新安装。
常用生产依赖示例:
Django
psycopg[binary]
gunicorn
ASGI 项目可选择 Uvicorn 等 ASGI 服务器。根据实际部署选择 WSGI 或 ASGI,不必为了“完整”同时运行两套。
三、配置 PostgreSQL
环境变量:
DB_NAME=notes
DB_USER=notes_app
DB_PASSWORD=change-me
DB_HOST=127.0.0.1
DB_PORT=5432
settings/production.py:
import os
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ.get("DB_PORT", "5432"),
"CONN_MAX_AGE": 60,
"CONN_HEALTH_CHECKS": True,
}
}
数据库用户只授予应用所需权限。生产库不能对公网开放;备份应加密,并定期进行恢复演练。
四、生产配置
DEBUG = False
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
ALLOWED_HOSTS = ["app.example.com"]
CSRF_TRUSTED_ORIGINS = ["https://app.example.com"]
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_ROOT = BASE_DIR / "media"
如果 TLS 在可信反向代理终止:
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
只有代理会覆盖客户端传入的该请求头时才可这样配置,否则可能被伪造。
五、发布前命令
python manage.py check --deploy
python manage.py migrate --noinput
python manage.py collectstatic --noinput
迁移前先备份。重要表的大型迁移要评估锁表时间、磁盘空间与回滚方式,必要时拆分为兼容旧代码的多个发布步骤。
六、运行应用服务器
WSGI 使用 Gunicorn:
gunicorn mysite.wsgi:application \
--bind 127.0.0.1:8000 \
--workers 3 \
--timeout 60
ASGI 使用 Uvicorn:
uvicorn mysite.asgi:application \
--host 127.0.0.1 \
--port 8000 \
--workers 3
Worker 数量需要根据 CPU、内存、请求特征和数据库连接上限压测决定,不要机械复制固定公式。
生产中应交给 systemd、容器编排或平台进程管理器自动启动、停止和重启。
七、systemd 服务示例
[Unit]
Description=Django notes application
After=network.target
[Service]
User=django
Group=django
WorkingDirectory=/srv/notes
EnvironmentFile=/etc/notes/notes.env
ExecStart=/srv/notes/.venv/bin/gunicorn mysite.wsgi:application --bind 127.0.0.1:8000 --workers 3
Restart=on-failure
PrivateTmp=true
[Install]
WantedBy=multi-user.target
运行用户不应是 root,只授予项目目录、日志和媒体目录所需权限。环境变量文件应限制读取权限。
八、Nginx 示例
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
client_max_body_size 10m;
location /static/ {
alias /srv/notes/staticfiles/;
expires 30d;
}
location /media/ {
alias /srv/notes/media/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
}
私有媒体文件不能直接暴露整个 /media/,应由 Django 鉴权后使用内部重定向、对象存储签名 URL 等方式提供。
九、容器部署注意事项
- 镜像固定依赖并使用非 root 用户。
- 配置通过环境变量或密钥挂载注入。
- 容器文件系统不是持久存储,媒体文件放对象存储或持久卷。
- 不要让每个应用副本同时无控制地执行迁移。
- 提供存活检查与就绪检查。
- 优雅关闭时停止接收新请求,并给正在处理的请求合理时间结束。
十、健康检查与可观测性
简单存活检查不必访问所有下游服务:
from django.http import JsonResponse
def health_live(request):
return JsonResponse({"status": "ok"})
就绪检查可以确认数据库等关键依赖可用,但要设置短超时,避免检查本身拖垮系统。
上线至少监控:
- HTTP 错误率和响应时间。
- 应用进程、CPU、内存和重启次数。
- 数据库连接、慢查询和磁盘空间。
- 任务队列积压和失败率。
- TLS 证书与域名到期时间。
十一、标准发布流程
- 构建不可变版本并运行测试。
- 备份数据库并确认恢复方式。
- 发布兼容当前数据库结构的代码。
- 执行迁移和静态文件收集。
- 滚动重启应用实例。
- 执行冒烟测试并观察指标。
- 异常时按预案回滚代码或向前修复迁移。
尽量做到旧代码与新数据库短时间兼容,避免发布过程中不同实例版本互相冲突。
十二、本篇检查清单
- 生产环境不使用
runserver和 SQLite。 - 配置、密钥、数据库和媒体文件有明确归属。
- 发布时执行部署检查、迁移和静态文件收集。
- HTTPS、代理头和私有文件访问配置正确。
- 有健康检查、监控、备份和回滚流程。
上一篇:Web 安全与生产配置 | 下一篇:综合实战项目与进阶路线