Flask部署详细介绍
本文介绍了Python Flask应用的生产环境部署方案。首先详细说明了生产环境配置,包括数据库、安全设置和邮件服务的配置方法,以及环境变量的设置。其次讲解了使用Gunicorn部署应用的步骤,包括安装配置、WSGI入口文件创建和参数优化。然后介绍了Nginx作为反向代理的安装和配置过程,包括静态文件处理、安全头设置等。接着说明了使用Systemd管理服务的方法,包括服务文件创建和服务管理命令。最
·
1. 部署准备
1.1 生产环境配置
# config.py
import os
class ProductionConfig:
DEBUG = False
TESTING = False
SECRET_KEY = os.environ.get('SECRET_KEY') or 'your-production-secret-key'
# 数据库配置
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 安全配置
SESSION_COOKIE_SECURE = True
REMEMBER_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
REMEMBER_COOKIE_HTTPONLY = True
# 邮件配置
MAIL_SERVER = os.environ.get('MAIL_SERVER')
MAIL_PORT = int(os.environ.get('MAIL_PORT', 587))
MAIL_USE_TLS = True
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
1.2 环境变量设置
# 创建 .env 文件(不要提交到版本控制)
echo "SECRET_KEY=your-super-secret-key-here" > .env
echo "DATABASE_URL=postgresql://username:password@localhost/dbname" >> .env
echo "MAIL_SERVER=smtp.gmail.com" >> .env
echo "MAIL_USERNAME=your-email@gmail.com" >> .env
echo "MAIL_PASSWORD=your-app-password" >> .env
# 加载环境变量
export $(grep -v '^#' .env | xargs)
2. 使用 Gunicorn 部署
2.1 安装 Gunicorn
pip install gunicorn
# 将依赖保存到 requirements.txt
pip freeze > requirements.txt
2.2 创建 WSGI 入口文件
# wsgi.py
from app import create_app
from app.config import ProductionConfig
app = create_app(ProductionConfig)
if __name__ == '__main__':
app.run()
2.3 使用 Gunicorn 启动应用
# 基本启动
gunicorn -w 4 -b 0.0.0.0:8000 wsgi:app
# 带更多配置的启动
gunicorn -w 4 -b 0.0.0.0:8000 \
--access-logfile - \
--error-logfile - \
--preload \
--timeout 120 \
wsgi:app
2.4 Gunicorn 配置文件
# gunicorn.conf.py
import multiprocessing
# 服务器绑定
bind = "0.0.0.0:8000"
# 工作进程数
workers = multiprocessing.cpu_count() * 2 + 1
# 工作模式
worker_class = "sync"
# 最大客户端连接数
worker_connections = 1000
# 超时时间
timeout = 120
# 守护进程
daemon = False
# 访问日志
accesslog = "-"
# 错误日志
errorlog = "-"
# 日志级别
loglevel = "info"
# 预加载应用
preload_app = True
# 最大请求数(防止内存泄漏)
max_requests = 1000
max_requests_jitter = 100
启动命令:
gunicorn -c gunicorn.conf.py wsgi:app
3. 使用 Nginx 作为反向代理
3.1 安装 Nginx
# Ubuntu/Debian
sudo apt update
sudo apt install nginx
# CentOS/RHEL
sudo yum install nginx
3.2 Nginx 配置文件
# /etc/nginx/sites-available/yourdomain.com
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# 静态文件处理
location /static {
alias /path/to/your/app/static;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media {
alias /path/to/your/app/media;
expires 30d;
}
# 反向代理到 Gunicorn
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;
# WebSocket 支持(如果需要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
}
# HTTP 重定向到 HTTPS(如果使用 SSL)
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
启用站点:
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t # 测试配置
sudo systemctl restart nginx
4. 使用 Systemd 管理服务
4.1 创建 Systemd 服务文件
# /etc/systemd/system/yourapp.service
[Unit]
Description=Gunicorn instance to serve your Flask app
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/your/app
Environment="PATH=/path/to/your/venv/bin"
Environment="SECRET_KEY=your-secret-key"
Environment="DATABASE_URL=your-database-url"
ExecStart=/path/to/your/venv/bin/gunicorn -c gunicorn.conf.py wsgi:app
ExecReload=/bin/kill -s HUP $MAINPID
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
4.2 管理服务
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start yourapp
# 启用开机自启
sudo systemctl enable yourapp
# 查看服务状态
sudo systemctl status yourapp
# 查看日志
sudo journalctl -u yourapp -f
5. 使用 Docker 部署
5.1 创建 Dockerfile
# Dockerfile
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
COPY requirements.txt .
# 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 创建非 root 用户
RUN useradd --create-home --shell /bin/bash app
USER app
# 暴露端口
EXPOSE 8000
# 启动命令
CMD ["gunicorn", "-c", "gunicorn.conf.py", "wsgi:app"]
5.2 创建 docker-compose.yml
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- SECRET_KEY=your-secret-key
- DATABASE_URL=postgresql://user:password@db:5432/yourapp
depends_on:
- db
volumes:
- ./logs:/app/logs
restart: unless-stopped
db:
image: postgres:13
environment:
- POSTGRES_DB=yourapp
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- web
restart: unless-stopped
volumes:
postgres_data:
5.3 构建和运行
# 构建镜像
docker-compose build
# 启动服务
docker-compose up -d
# 查看日志
docker-compose logs -f
6. 使用云平台部署
6.1 Heroku 部署
# 创建 Procfile
echo "web: gunicorn -w 4 -b 0.0.0.0:\$PORT wsgi:app" > Procfile
# 创建 runtime.txt
echo "python-3.9.7" > runtime.txt
# 部署到 Heroku
heroku create yourapp-name
heroku config:set SECRET_KEY=your-secret-key
heroku addons:create heroku-postgresql:hobby-dev
git push heroku main
6.2 PythonAnywhere 部署
# 在 PythonAnywhere 的 WSGI 配置文件
import sys
path = '/home/yourusername/yourapp'
if path not in sys.path:
sys.path.append(path)
from wsgi import app as application
7. 数据库迁移和初始化
7.1 使用 Flask-Migrate
# 在应用初始化中添加
from flask_migrate import Migrate
migrate = Migrate()
def create_app(config_class=ProductionConfig):
app = Flask(__name__)
app.config.from_object(config_class)
# 初始化扩展
db.init_app(app)
migrate.init_app(app, db)
return app
7.2 部署时的数据库操作
# 进入应用目录
cd /path/to/your/app
# 激活虚拟环境
source venv/bin/activate
# 初始化迁移(首次部署)
flask db init
# 生成迁移脚本
flask db migrate -m "Initial migration"
# 应用迁移
flask db upgrade
# 或者在代码中处理
@app.before_first_request
def create_tables():
db.create_all()
8. SSL/TLS 配置(HTTPS)
8.1 使用 Let’s Encrypt
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx
# 获取证书
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# 自动续期测试
sudo certbot renew --dry-run
8.2 Nginx SSL 配置
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers off;
# 其他配置同上...
}
9. 监控和日志
9.1 日志配置
# logging_config.py
import logging
from logging.handlers import RotatingFileHandler
import os
def setup_logging(app):
if not app.debug:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler(
'logs/yourapp.log',
maxBytes=10240,
backupCount=10
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Application startup')
9.2 健康检查端点
@app.route('/health')
def health_check():
return jsonify({'status': 'healthy', 'timestamp': datetime.utcnow().isoformat()})
@app.route('/metrics')
@login_required # 如果需要认证
def metrics():
# 返回应用指标
return jsonify({
'active_users': get_active_users_count(),
'memory_usage': get_memory_usage(),
'database_connections': get_db_connections()
})
10. 部署脚本示例
10.1 自动化部署脚本
#!/bin/bash
# deploy.sh
echo "开始部署 Flask 应用..."
# 拉取最新代码
git pull origin main
# 激活虚拟环境
source venv/bin/activate
# 安装依赖
pip install -r requirements.txt
# 运行数据库迁移
flask db upgrade
# 收集静态文件(如果需要)
# flask collectstatic
# 重启应用
sudo systemctl restart yourapp
# 重启 Nginx
sudo systemctl reload nginx
echo "部署完成!"
10.2 使用 Makefile
# Makefile
.PHONY: deploy test migrate
deploy:
git pull origin main
pip install -r requirements.txt
flask db upgrade
sudo systemctl restart yourapp
sudo systemctl reload nginx
test:
pytest
migrate:
flask db migrate -m "Auto migration"
flask db upgrade
logs:
sudo journalctl -u yourapp -f
11. 安全最佳实践
11.1 安全配置
class ProductionConfig:
# 安全相关配置
SESSION_COOKIE_SECURE = True
REMEMBER_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
REMEMBER_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
# 防止点击劫持
@app.after_request
def set_security_headers(response):
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-XSS-Protection'] = '1; mode=block'
return response
11.2 防火墙配置
# 配置 UFW 防火墙
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
12. 性能优化
12.1 Gunicorn 优化配置
# gunicorn_optimized.conf.py
import multiprocessing
bind = "unix:/tmp/yourapp.sock"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "gthread"
threads = 4
worker_connections = 1000
max_requests = 1000
max_requests_jitter = 100
preload_app = True
timeout = 120
12.2 使用缓存
from flask_caching import Cache
cache = Cache(config={'CACHE_TYPE': 'RedisCache', 'CACHE_REDIS_URL': 'redis://localhost:6379/0'})
@app.route('/expensive-operation')
@cache.cached(timeout=300) # 缓存5分钟
def expensive_operation():
# 耗时操作
return expensive_result
部署检查清单
- 配置文件已设置为生产环境
- 环境变量已正确设置
- 数据库已迁移到最新版本
- 静态文件已正确配置
- SSL证书已安装和配置
- 防火墙规则已设置
- 监控和日志已配置
- 备份策略已制定
- 域名解析已设置
- 测试所有功能是否正常
选择适合你项目规模的部署方式。小型项目可以从简单的 Gunicorn + Nginx 开始,大型项目可以考虑 Docker 和云平台部署。
更多推荐



所有评论(0)