1. 项目概述:现代化Web应用部署方案
十年前我刚入行时,部署Python Web应用还需要手动配置虚拟环境、处理依赖冲突、折腾WSGI服务器。现在用Docker+Nginx的方案,整个过程就像把家具打包进标准集装箱再配个智能物流系统 - 既保证环境一致性,又获得生产级性能。这个方案特别适合需要快速迭代的创业团队和个人开发者,我用这个组合部署过Django、Flask、FastAPI等各种框架的应用,下面就把这些年积累的最佳实践一次性说明白。
2. 环境准备与工具选型
2.1 基础环境配置
我的主力服务器是Ubuntu 22.04 LTS,这个长期支持版本对Docker的兼容性最好。先做这三件事:
- 更新软件源并安装基础工具包:
sudo apt update && sudo apt upgrade -y sudo apt install -y git curl net-tools- 设置swap分区(1GB内存的服务器必备):
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab- 配置防火墙规则(只开放必要端口):
sudo ufw allow 22/tcp # SSH sudo ufw allow 80/tcp # HTTP sudo ufw allow 443/tcp # HTTPS sudo ufw enable注意:云服务器还需要在控制台配置安全组规则,这是新手常踩的坑
2.2 Docker引擎安装
我推荐使用官方安装脚本而非系统自带版本:
curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER newgrp docker # 立即生效验证安装成功后,配置国内镜像加速(否则拉镜像会慢到怀疑人生):
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://registry.docker-cn.com"] } EOF sudo systemctl restart docker2.3 Nginx安装与基础配置
虽然可以用Docker跑Nginx,但我更推荐主机直接安装:
sudo apt install -y nginx sudo systemctl enable nginx关键目录说明:
/etc/nginx/nginx.conf主配置文件/etc/nginx/sites-available/虚拟主机配置/etc/nginx/sites-enabled/启用的站点(软链接)
3. Docker化Python应用
3.1 项目结构规范
这是我常用的标准目录结构:
myapp/ ├── app/ # 应用代码 │ ├── __init__.py │ └── main.py ├── requirements.txt # 依赖文件 ├── Dockerfile # 构建定义 ├── docker-compose.yml # 服务编排 └── nginx/ └── myapp.conf # Nginx配置3.2 编写高效的Dockerfile
以FastAPI应用为例,这是经过优化的多阶段构建方案:
# 构建阶段 FROM python:3.9-slim as builder WORKDIR /app COPY requirements.txt . RUN pip install --user -r requirements.txt # 运行阶段 FROM python:3.9-slim WORKDIR /app COPY --from=builder /root/.local /root/.local COPY . . ENV PATH=/root/.local/bin:$PATH ENV PYTHONPATH=/app EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0"]关键优化点:
- 使用slim镜像减少体积(比常规镜像小40%)
- 多阶段构建避免携带构建工具到生产环境
- --user安装避免污染系统目录
3.3 依赖管理技巧
在requirements.txt中使用精确版本号:
fastapi==0.95.2 uvicorn==0.22.0 # 生产环境必须固定版本!生成依赖树(开发环境用):
pip freeze > requirements-dev.txt4. Nginx高级配置
4.1 反向代理配置
这是经过实战检验的Nginx配置模板:
upstream myapp { server 127.0.0.1:8000; keepalive 32; } server { listen 80; server_name yourdomain.com; location / { proxy_pass http://myapp; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # WebSocket支持 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # 静态文件优化 location /static/ { alias /path/to/static/files; expires 30d; access_log off; } }4.2 性能调优参数
在nginx.conf的http块添加这些关键参数:
http { # 连接优化 keepalive_timeout 65; keepalive_requests 1000; sendfile on; tcp_nopush on; # 缓冲控制 client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 20m; # 超时设置 client_body_timeout 12; client_header_timeout 12; send_timeout 10; }5. 部署与持续集成
5.1 使用docker-compose编排
这是我的生产级compose文件:
version: '3.8' services: app: build: . restart: unless-stopped ports: - "8000:8000" environment: - ENV=production volumes: - ./logs:/app/logs healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 5s retries: 3 nginx: image: nginx:alpine restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./nginx:/etc/nginx/conf.d - ./static:/var/www/static depends_on: - app启动命令:
docker-compose up -d --build5.2 日志管理方案
- 统一日志目录结构:
logs/ ├── app/ │ ├── access.log │ └── error.log └── nginx/ ├── access.log └── error.log- 使用logrotate自动切割:
sudo tee /etc/logrotate.d/myapp <<EOF /path/to/logs/*.log { daily missingok rotate 30 compress delaycompress notifempty create 0640 www-data www-data sharedscripts postrotate docker exec myapp_nginx_1 nginx -s reload endscript } EOF6. 安全加固措施
6.1 Docker安全实践
- 非root用户运行容器:
RUN useradd -m myuser USER myuser- 只读文件系统:
services: app: read_only: true tmpfs: - /tmp- 资源限制:
deploy: resources: limits: cpus: '2' memory: 1G6.2 Nginx安全头配置
在server块添加这些关键头:
add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; add_header Referrer-Policy "strict-origin-when-cross-origin"; add_header Content-Security-Policy "default-src 'self'";7. 性能监控与维护
7.1 基础监控方案
- 查看容器状态:
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"- Nginx状态监控:
location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; deny all; }7.2 零停机部署技巧
使用双容器滚动更新:
# 启动新版本容器 docker-compose up -d --no-deps --scale app=2 --no-recreate app # 等待健康检查通过 sleep 10 # 停掉旧容器 docker-compose up -d --no-deps --scale app=1 --no-recreate app8. 常见问题排错指南
8.1 连接问题排查流程
- 检查容器是否运行:
docker ps -a --filter "name=myapp"- 查看应用日志:
docker logs myapp_app_1- 测试容器内连通性:
docker exec -it myapp_app_1 curl http://localhost:80008.2 典型错误解决方案
问题1:502 Bad Gateway
- 检查应用容器是否崩溃
- 验证Nginx的upstream配置
- 查看防火墙规则
问题2:静态文件404
- 确认volume挂载路径
- 检查文件权限
- 验证Nginx的alias配置
问题3:数据库连接失败
- 检查容器网络模式
- 验证连接字符串
- 测试端口连通性
这套方案在我经手的十几个项目中表现稳定,特别是配合CI/CD流水线后,部署过程从原来的小时级缩短到分钟级。最后提醒一点:一定要在本地用相同的Docker环境测试通过后再部署到服务器,能避免90%的运行时问题。