473 lines
7.8 KiB
Markdown
473 lines
7.8 KiB
Markdown
|
|
# 城市手册项目部署指南
|
|||
|
|
|
|||
|
|
## 部署前准备
|
|||
|
|
|
|||
|
|
### 1. 环境要求
|
|||
|
|
|
|||
|
|
- Python 3.11+
|
|||
|
|
- Node.js 18+
|
|||
|
|
- PostgreSQL 15+
|
|||
|
|
- Docker & Docker Compose(可选)
|
|||
|
|
- Nginx(可选)
|
|||
|
|
|
|||
|
|
### 2. 数据库配置
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 创建数据库
|
|||
|
|
createdb citywiki
|
|||
|
|
|
|||
|
|
# 或使用 Docker
|
|||
|
|
docker run -d \
|
|||
|
|
--name citywiki-db \
|
|||
|
|
-e POSTGRES_DB=citywiki \
|
|||
|
|
-e POSTGRES_USER=citywiki \
|
|||
|
|
-e POSTGRES_PASSWORD=your_password \
|
|||
|
|
-p 5432:5432 \
|
|||
|
|
postgres:15-alpine
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 环境变量配置
|
|||
|
|
|
|||
|
|
复制 `.env.example` 到 `.env` 并配置:
|
|||
|
|
|
|||
|
|
```env
|
|||
|
|
# Django Settings
|
|||
|
|
DJANGO_SECRET_KEY=your-secret-key-here
|
|||
|
|
DJANGO_DEBUG=False
|
|||
|
|
|
|||
|
|
# Database
|
|||
|
|
DB_NAME=citywiki
|
|||
|
|
DB_USER=citywiki
|
|||
|
|
DB_PASSWORD=your_password
|
|||
|
|
DB_HOST=localhost
|
|||
|
|
DB_PORT=5432
|
|||
|
|
|
|||
|
|
# Allowed Hosts
|
|||
|
|
ALLOWED_HOSTS=localhost,yourdomain.com
|
|||
|
|
|
|||
|
|
# CORS
|
|||
|
|
CORS_ALLOWED_ORIGINS=http://localhost,https://yourdomain.com
|
|||
|
|
|
|||
|
|
# Email(可选)
|
|||
|
|
EMAIL_HOST=smtp.gmail.com
|
|||
|
|
EMAIL_PORT=587
|
|||
|
|
EMAIL_HOST_USER=your-email@example.com
|
|||
|
|
EMAIL_HOST_PASSWORD=your-email-password
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 部署方式
|
|||
|
|
|
|||
|
|
### 方式一:Docker Compose(推荐)
|
|||
|
|
|
|||
|
|
#### 1. 构建镜像
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker-compose build
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. 启动服务
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker-compose up -d
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3. 运行迁移
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker-compose exec backend python manage.py migrate
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4. 创建超级用户
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker-compose exec backend python manage.py createsuperuser
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 5. 查看日志
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker-compose logs -f
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 6. 停止服务
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker-compose down
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 方式二:手动部署
|
|||
|
|
|
|||
|
|
#### 后端部署
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd backend
|
|||
|
|
|
|||
|
|
# 创建虚拟环境
|
|||
|
|
python -m venv venv
|
|||
|
|
source venv/bin/activate # Windows: venv\Scripts\activate
|
|||
|
|
|
|||
|
|
# 安装依赖
|
|||
|
|
pip install -r requirements.txt
|
|||
|
|
|
|||
|
|
# 配置环境变量
|
|||
|
|
cp .env.example .env
|
|||
|
|
# 编辑 .env 文件
|
|||
|
|
|
|||
|
|
# 运行迁移
|
|||
|
|
python manage.py migrate
|
|||
|
|
|
|||
|
|
# 收集静态文件
|
|||
|
|
python manage.py collectstatic --noinput
|
|||
|
|
|
|||
|
|
# 创建超级用户
|
|||
|
|
python manage.py createsuperuser
|
|||
|
|
|
|||
|
|
# 启动服务(生产环境)
|
|||
|
|
gunicorn config.wsgi:application --bind 0.0.0.0:8000 --workers 3
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 前端部署
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd frontend
|
|||
|
|
|
|||
|
|
# 安装依赖
|
|||
|
|
npm install
|
|||
|
|
|
|||
|
|
# 配置环境变量
|
|||
|
|
cp .env.example .env
|
|||
|
|
# 编辑 .env 文件
|
|||
|
|
|
|||
|
|
# 构建
|
|||
|
|
npm run build
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 方式三:Nginx 部署
|
|||
|
|
|
|||
|
|
#### Nginx 配置
|
|||
|
|
|
|||
|
|
```nginx
|
|||
|
|
server {
|
|||
|
|
listen 80;
|
|||
|
|
server_name yourdomain.com;
|
|||
|
|
|
|||
|
|
# 前端静态文件
|
|||
|
|
location / {
|
|||
|
|
root /path/to/frontend/build;
|
|||
|
|
try_files $uri $uri/ /index.html;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# API 代理
|
|||
|
|
location /api/ {
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# GraphQL 代理
|
|||
|
|
location /graphql/ {
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 静态文件
|
|||
|
|
location /static/ {
|
|||
|
|
alias /path/to/backend/staticfiles/;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 媒体文件
|
|||
|
|
location /media/ {
|
|||
|
|
alias /path/to/backend/media/;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 启动服务
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 启动后端
|
|||
|
|
cd backend
|
|||
|
|
source venv/bin/activate
|
|||
|
|
gunicorn config.wsgi:application --bind 127.0.0.1:8000 --workers 3
|
|||
|
|
|
|||
|
|
# 启动 Nginx
|
|||
|
|
sudo nginx -t
|
|||
|
|
sudo systemctl restart nginx
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 生产环境配置
|
|||
|
|
|
|||
|
|
### 1. Django 配置
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# config/settings/prod.py
|
|||
|
|
DEBUG = False
|
|||
|
|
|
|||
|
|
# 安全设置
|
|||
|
|
SECURE_BROWSER_XSS_FILTER = True
|
|||
|
|
SECURE_CONTENT_TYPE_NOSNIFF = True
|
|||
|
|
SECURE_HSTS_SECONDS = 31536000
|
|||
|
|
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
|||
|
|
SECURE_HSTS_PRELOAD = True
|
|||
|
|
SECURE_SSL_REDIRECT = True
|
|||
|
|
|
|||
|
|
# 允许的主机
|
|||
|
|
ALLOWED_HOSTS = ['yourdomain.com']
|
|||
|
|
|
|||
|
|
# 数据库(使用 Unix socket 更快)
|
|||
|
|
DATABASES = {
|
|||
|
|
'default': {
|
|||
|
|
'ENGINE': 'django.db.backends.postgresql',
|
|||
|
|
'NAME': 'citywiki',
|
|||
|
|
'USER': 'citywiki',
|
|||
|
|
'PASSWORD': 'your_password',
|
|||
|
|
'HOST': '/var/run/postgresql',
|
|||
|
|
'PORT': '',
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. Gunicorn 配置
|
|||
|
|
|
|||
|
|
创建 `gunicorn.conf.py`:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
bind = "127.0.0.1:8000"
|
|||
|
|
workers = 3
|
|||
|
|
worker_class = "sync"
|
|||
|
|
worker_connections = 1000
|
|||
|
|
max_requests = 1000
|
|||
|
|
max_requests_jitter = 50
|
|||
|
|
timeout = 30
|
|||
|
|
keepalive = 2
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
启动 Gunicorn:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
gunicorn -c gunicorn.conf.py config.wsgi:application
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. Systemd 服务(自动重启)
|
|||
|
|
|
|||
|
|
创建 `/etc/systemd/system/citywiki.service`:
|
|||
|
|
|
|||
|
|
```ini
|
|||
|
|
[Unit]
|
|||
|
|
Description=CityWiki Django App
|
|||
|
|
After=network.target
|
|||
|
|
|
|||
|
|
[Service]
|
|||
|
|
User=www-data
|
|||
|
|
Group=www-data
|
|||
|
|
WorkingDirectory=/path/to/backend
|
|||
|
|
ExecStart=/path/to/backend/venv/bin/gunicorn -c gunicorn.conf.py config.wsgi:application
|
|||
|
|
Restart=always
|
|||
|
|
|
|||
|
|
[Install]
|
|||
|
|
WantedBy=multi-user.target
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
启动服务:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
sudo systemctl daemon-reload
|
|||
|
|
sudo systemctl start citywiki
|
|||
|
|
sudo systemctl enable citywiki
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 监控和日志
|
|||
|
|
|
|||
|
|
### 1. Django 日志配置
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
LOGGING = {
|
|||
|
|
'version': 1,
|
|||
|
|
'disable_existing_loggers': False,
|
|||
|
|
'handlers': {
|
|||
|
|
'file': {
|
|||
|
|
'level': 'INFO',
|
|||
|
|
'class': 'logging.FileHandler',
|
|||
|
|
'filename': '/var/log/citywiki/django.log',
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
'loggers': {
|
|||
|
|
'django': {
|
|||
|
|
'handlers': ['file'],
|
|||
|
|
'level': 'INFO',
|
|||
|
|
'propagate': True,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. Nginx 日志
|
|||
|
|
|
|||
|
|
```nginx
|
|||
|
|
access_log /var/log/nginx/citywiki_access.log;
|
|||
|
|
error_log /var/log/nginx/citywiki_error.log;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 数据备份
|
|||
|
|
|
|||
|
|
### PostgreSQL 备份
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 备份
|
|||
|
|
pg_dump -U citywiki citywiki > backup_$(date +%Y%m%d).sql
|
|||
|
|
|
|||
|
|
# 恢复
|
|||
|
|
psql -U citywiki citywiki < backup_20260409.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 媒体文件备份
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
rsync -avz /path/to/backend/media/ /backup/media/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## HTTPS 配置(Let's Encrypt)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 安装 Certbot
|
|||
|
|
sudo apt-get install certbot python3-certbot-nginx
|
|||
|
|
|
|||
|
|
# 获取证书
|
|||
|
|
sudo certbot --nginx -d yourdomain.com
|
|||
|
|
|
|||
|
|
# 自动续期
|
|||
|
|
sudo certbot renew --dry-run
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 性能优化
|
|||
|
|
|
|||
|
|
### 1. 数据库优化
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 添加索引
|
|||
|
|
CREATE INDEX idx_articles_region ON articles(region_id);
|
|||
|
|
CREATE INDEX idx_articles_status ON articles(publish_status);
|
|||
|
|
CREATE INDEX idx_services_region ON featured_services(region_id);
|
|||
|
|
CREATE INDEX idx_services_status ON featured_services(publish_status);
|
|||
|
|
CREATE INDEX idx_comments_target ON comments(target_type, target_id);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 缓存(Redis)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 安装 Redis
|
|||
|
|
sudo apt-get install redis-server
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
配置 Django 使用 Redis:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
CACHES = {
|
|||
|
|
'default': {
|
|||
|
|
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
|
|||
|
|
'LOCATION': 'redis://127.0.0.1:6379/1',
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. CDN 加速
|
|||
|
|
|
|||
|
|
使用 Cloudflare 或阿里云 CDN 加速静态文件访问。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 故障排查
|
|||
|
|
|
|||
|
|
### 1. 数据库连接失败
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 检查 PostgreSQL 是否运行
|
|||
|
|
sudo systemctl status postgresql
|
|||
|
|
|
|||
|
|
# 检查端口
|
|||
|
|
sudo netstat -tuln | grep 5432
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 静态文件 404
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 重新收集静态文件
|
|||
|
|
cd backend
|
|||
|
|
python manage.py collectstatic --noinput
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. Nginx 502 Bad Gateway
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 检查 Django 是否运行
|
|||
|
|
ps aux | grep gunicorn
|
|||
|
|
|
|||
|
|
# 重启 Django
|
|||
|
|
sudo systemctl restart citywiki
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 更新部署
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 拉取最新代码
|
|||
|
|
git pull origin master
|
|||
|
|
|
|||
|
|
# 后端更新
|
|||
|
|
cd backend
|
|||
|
|
source venv/bin/activate
|
|||
|
|
pip install -r requirements.txt
|
|||
|
|
python manage.py migrate
|
|||
|
|
python manage.py collectstatic --noinput
|
|||
|
|
sudo systemctl restart citywiki
|
|||
|
|
|
|||
|
|
# 前端更新
|
|||
|
|
cd frontend
|
|||
|
|
npm install
|
|||
|
|
npm run build
|
|||
|
|
sudo systemctl restart nginx
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 安全检查清单
|
|||
|
|
|
|||
|
|
- [ ] 更改 Django SECRET_KEY
|
|||
|
|
- [ ] 设置 DEBUG=False
|
|||
|
|
- [ ] 配置 ALLOWED_HOSTS
|
|||
|
|
- [ ] 启用 HTTPS
|
|||
|
|
- [ ] 配置数据库防火墙
|
|||
|
|
- [ ] 定期备份数据
|
|||
|
|
- [ ] 更新依赖包
|
|||
|
|
- [ ] 监控日志文件
|
|||
|
|
- [ ] 配置 fail2ban
|
|||
|
|
- [ ] 定期安全审计
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 参考资料
|
|||
|
|
|
|||
|
|
- [Django 部署指南](https://docs.djangoproject.com/en/4.2/howto/deployment/)
|
|||
|
|
- [Gunicorn 文档](https://docs.gunicorn.org/en/stable/)
|
|||
|
|
- [Nginx 文档](https://nginx.org/en/docs/)
|
|||
|
|
- [Docker Compose 文档](https://docs.docker.com/compose/)
|