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/) |