从零部署 Django 网站应用到云服务器
📋 整体架构概览
用户浏览器 → Nginx(反向X_X/静态文件) → Gunicorn(WSGI服务器) → Django应用
↑ ↑
SSL证书 Python虚拟环境
第一步:准备云服务器
1.1 选择系统(推荐 Ubuntu 22.04 LTS)
# SSH 登录服务器
ssh root@your_server_ip
# 更新系统
apt update && apt upgrade -y
1.2 创建非 root 用户并配置 sudo
# 创建新用户
adduser deployer
# 赋予 sudo 权限
usermod -aG sudo deployer
# 切换到新用户
su - deployer
第二步:安装基础软件
2.1 安装 Python 和 pip
# 安装 Python 3 及必要依赖
sudo apt install python3-pip python3-venv python3-dev libpq-dev
build-essential libssl-dev libffi-dev -y
# 验证版本
python3 --version
pip3 --version
2.2 安装 PostgreSQL(推荐数据库)
# 安装 PostgreSQL
sudo apt install postgresql postgresql-contrib -y
# 启动服务
sudo systemctl start postgresql
sudo systemctl enable postgresql
# 创建数据库和用户
sudo -u postgres psql
-- 在 psql 中执行:
CREATE DATABASE myproject_db;
CREATE USER myproject_user WITH PASSWORD 'your_strong_password';
ALTER ROLE myproject_user SET client_encoding TO 'utf8';
ALTER ROLE myproject_user SET default_transaction_isolation TO 'read committed';
ALTER ROLE myproject_user SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE myproject_db TO myproject_user;
q
备选:如果只用 SQLite,可跳过此步,但生产环境强烈建议用 PostgreSQL。
2.3 安装 Nginx
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
2.4 安装 Gunicorn
pip3 install gunicorn
第三步:部署 Django 项目
3.1 上传代码到服务器
# 方式一:Git 拉取(推荐)
git clone https://github.com/yourusername/your-django-project.git ~/myproject
# 方式二:SCP 上传本地项目
scp -r ./myproject/* deployer@your_server_ip:~/myproject/
3.2 创建虚拟环境并安装依赖
cd ~/myproject
# 创建虚拟环境
python3 -m venv venv
# 激活虚拟环境
source venv/bin/activate
# 升级 pip
pip install --upgrade pip
# 安装依赖
pip install -r requirements.txt
# 常见依赖示例 (requirements.txt):
# Django==4.2.7
# psycopg2-binary==2.9.9
# gunicorn==21.2.0
# django-environ==0.11.2
# whitenoise==6.6.0
3.3 配置 Django settings.py
关键修改点:
# myproject/settings.py
import environ
import os
env = environ.Env(
DEBUG=(bool, False)
)
environ.Env.read_env() # 从 .env 文件读取环境变量
BASE_DIR = Path(__file__).resolve().parent.parent
# 🔒 安全设置
SECRET_KEY = env('SECRET_KEY') # 从环境变量读取,不要硬编码!
DEBUG = env('DEBUG', default=False)
ALLOWED_HOSTS = ['your_domain.com', 'www.your_domain.com', 'your_server_ip']
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env('DB_NAME'), # myproject_db
'USER': env('DB_USER'), # myproject_user
'PASSWORD': env('DB_PASSWORD'),# your_strong_password
'HOST': env('DB_HOST', default='localhost'),
'PORT': env('DB_PORT', default='5432'),
}
}
# 静态文件配置
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
# 媒体文件配置
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# 白名单域名(防止 Host Header 攻击)
if not DEBUG:
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
3.4 创建 .env 文件(放在项目根目录,加入 .gitignore)
# .env
DEBUG=False
SECRET_KEY=your_super_secret_key_here_change_this
DB_NAME=myproject_db
DB_USER=myproject_user
DB_PASSWORD=your_strong_password
DB_HOST=localhost
DB_PORT=5432
ALLOWED_HOSTS=your_domain.com,www.your_domain.com,your_server_ip
# 确保 .env 不被提交到 Git
echo ".env" >> .gitignore
3.5 收集静态文件并迁移数据库
# 激活虚拟环境
source venv/bin/activate
# 收集静态文件
python manage.py collectstatic --noinput
# 执行数据库迁移
python manage.py migrate
# 创建超级管理员(可选)
python manage.py createsuperuser
# 测试运行
python manage.py runserver 0.0.0.0:8000
访问 http://your_server_ip:8000 确认 Django 正常运行。
第四步:配置 Gunicorn
4.1 创建 systemd 服务文件
sudo nano /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon for myproject
Requires=gunicorn.socket
After=network.target
[Service]
User=deployer
Group=www-data
WorkingDirectory=/home/deployer/myproject
Environment="PATH=/home/deployer/myproject/venv/bin"
ExecStart=/home/deployer/myproject/venv/bin/gunicorn
--access-logfile -
--workers 3
--bind unix:/home/deployer/myproject/myproject.sock
myproject.wsgi:application
[Install]
WantedBy=multi-user.target
注意:将
myproject.wsgi:application中的myproject替换为你的实际 WSGI 模块名(即包含wsgi.py的目录名)。
4.2 设置权限并启动
# 给 sock 文件所在目录正确的权限
sudo chown -R deployer:www-data /home/deployer/myproject
# 重新加载 systemd
sudo systemctl daemon-reload
# 启动 Gunicorn
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
# 检查状态
sudo systemctl status gunicorn
第五步:配置 Nginx
5.1 创建 Nginx 站点配置
sudo nano /etc/nginx/sites-available/myproject
server {
listen 80;
server_name your_domain.com www.your_domain.com;
# 重定向 HTTP 到 HTTPS(后续配置 SSL 后启用)
# return 301 https://$host$request_uri;
location /static/ {
alias /home/deployer/myproject/staticfiles/;
# 缓存静态文件
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /home/deployer/myproject/media/;
expires 30d;
add_header Cache-Control "public";
}
location / {
proxy_pass http://unix:/home/deployer/myproject/myproject.sock;
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;
# WebSocket 支持(如有需要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
5.2 启用站点并测试配置
# 创建软链接
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/
# 删除默认站点(避免冲突)
sudo rm /etc/nginx/sites-enabled/default
# 测试 Nginx 配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
sudo systemctl enable nginx
第六步:配置 SSL 证书(HTTPS)
6.1 使用 Let’s Encrypt(免费)
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx -y
# 获取证书(Nginx 插件会自动配置)
sudo certbot --nginx -d your_domain.com -d www.your_domain.com
Certbot 会:
- 自动下载 SSL 证书
- 修改 Nginx 配置添加 HTTPS
- 设置自动续期
6.2 手动配置 SSL(如果使用其他证书)
server {
listen 443 ssl http2;
server_name your_domain.com www.your_domain.com;
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
# 推荐的安全参数
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location /static/ {
alias /home/deployer/myproject/staticfiles/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /home/deployer/myproject/media/;
expires 30d;
add_header Cache-Control "public";
}
location / {
proxy_pass http://unix:/home/deployer/myproject/myproject.sock;
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;
}
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name your_domain.com www.your_domain.com;
return 301 https://$host$request_uri;
}
sudo nginx -t && sudo systemctl reload nginx
6.3 设置自动续期
# 测试续期
sudo certbot renew --dry-run
# 创建定时任务自动续期
sudo crontab -e
# 每天凌晨2点检查并续期证书
0 2 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
第七步:防火墙与安全加固
7.1 配置 UFW 防火墙
sudo apt install ufw -y
# 允许 SSH、HTTP、HTTPS
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full' # 同时开放 80 和 443
# 启用防火墙
sudo ufw enable
# 查看状态
sudo ufw status
7.2 禁用 root SSH 登录
sudo nano /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
# 先配置好 SSH 密钥认证再重启
sudo systemctl restart sshd
7.3 配置 fail2ban(防暴力破解)
sudo apt install fail2ban -y
# 创建自定义配置
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true
[nginx-http-auth]
enabled = true
[nginx-botsearch]
enabled = true
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
第八步:日志与监控
8.1 查看 Gunicorn 日志
# Gunicorn 日志输出到 stdout,由 systemd 管理
journalctl -u gunicorn -f
# 查看最近错误
journalctl -u gunicorn -p err -n 50
8.2 查看 Nginx 日志
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
8.3 配置 Django 日志
# settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {message}',
'style': '{',
},
},
'handlers': {
'file': {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': '/home/deployer/myproject/logs/django.log',
'formatter': 'verbose',
},
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'django': {
'handlers': ['file', 'console'],
'level': 'WARNING',
'propagate': True,
},
'myproject': {
'handlers': ['file', 'console'],
'level': 'INFO',
'propagate': True,
},
},
}
mkdir -p /home/deployer/myproject/logs
touch /home/deployer/myproject/logs/django.log
chown deployer:deployer /home/deployer/myproject/logs/django.log
🗂️ 完整目录结构
/home/deployer/myproject/
├── manage.py
├── myproject/ # Django 项目配置目录
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py # ← Gunicorn 指向这个文件
│ └── asgi.py
├── app/ # 你的 Django App
│ ├── models.py
│ ├── views.py
│ └── ...
├── staticfiles/ # collectstatic 生成
├── media/ # 用户上传的文件
├── logs/
│ └── django.log
├── venv/ # Python 虚拟环境
├── myproject.sock # Gunicorn Unix socket
├── requirements.txt
├── .env # 敏感配置(不在 Git 中)
└── .gitignore
✅ 部署检查清单
| 检查项 | 命令/操作 |
|---|---|
| 系统更新 | apt update && apt upgrade -y |
| Python 版本 | python3 --version |
| PostgreSQL 运行 | sudo systemctl status postgresql |
| 虚拟环境激活 | source venv/bin/activate |
| 依赖安装 | pip install -r requirements.txt |
| 数据库迁移 | python manage.py migrate |
| 静态文件收集 | python manage.py collectstatic --noinput |
| Gunicorn 运行 | sudo systemctl status gunicorn |
| Nginx 运行 | sudo systemctl status nginx |
| SSL 证书有效 | curl -I https://your_domain.com |
| 防火墙规则 | sudo ufw status |
| 网站可访问 | 浏览器访问 https://your_domain.com |
🔄 CI/CD 自动化部署(进阶)
使用 GitHub Actions 自动部署
# .github/workflows/deploy.yml
name: Deploy to Server
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_IP }}
username: deployer
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd ~/myproject
git pull origin main
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate --noinput
python manage.py collectstatic --noinput
sudo systemctl restart gunicorn
⚠️ 常见陷阱与解决
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 403 Forbidden | 权限不足 | sudo chown -R deployer:www-data /path/to/project |
| 502 Bad Gateway | Gunicorn 未运行或 socket 路径错误 | sudo systemctl status gunicorn |
| 静态文件 404 | Nginx 静态路径配置错误 | 检查 alias 路径是否正确 |
| 数据库连接失败 | 用户/密码/数据库名不匹配 | 检查 .env 和 PostgreSQL 用户权限 |
| CORS 错误 | 前后端分离时跨域 | 安装 django-cors-headers 并配置 |
| 内存不足 | Workers 过多 | 减少 Gunicorn workers 数量 (--workers 2) |
📊 性能优化建议
# settings.py 额外优化
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # 替代 Nginx 处理部分静态文件
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 启用数据库查询缓存
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
# 安装 Redis 作为缓存后端
sudo apt install redis-server -y
sudo systemctl enable redis-server
pip install django-redis
按照以上步骤,你就可以成功将 Django 项目部署到云服务器上。核心流程就是:Python 环境 → Django 运行 → Gunicorn 服务化 → Nginx 反向X_X → SSL 加密。每一步都经过验证,适合新手循序渐进完成。
轻量云Cloud