1. 项目背景与核心价值
去年帮朋友部署一个Django项目时,我深刻体会到手工部署的繁琐:需要手动安装Python环境、配置uWSGI、处理静态文件、设置Nginx反向代理...整个过程至少需要半天时间,且环境差异经常导致各种报错。而采用Docker+Nginx的方案后,同样的部署流程缩短到15分钟,且完全规避了环境不一致的问题。
这种部署方式特别适合:
- 需要快速迭代的创业团队
- 同时维护多个项目的独立开发者
- 对服务器运维不熟悉但需要自主部署的后端工程师
2. 技术架构解析
2.1 整体工作流程
用户请求 -> Nginx(80端口) -> 静态文件直接响应 -> 动态请求转发 -> Docker容器(8000端口) -> Python应用2.2 关键技术组件
Docker容器化:
- 包含完整的Python运行环境
- 固定版本依赖(requirements.txt)
- 隔离主机环境
Nginx核心作用:
- 静态文件托管(CSS/JS/图片)
- 负载均衡(多容器时)
- HTTPS终端代理
- 请求缓存
3. 详细实施步骤
3.1 准备Docker镜像
以Django项目为例的Dockerfile:
# 使用官方Python镜像作为基础 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 先复制依赖文件单独安装(利用Docker缓存层) COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制项目代码 COPY . . # 收集静态文件 RUN python manage.py collectstatic --noinput # 暴露端口 EXPOSE 8000 # 启动命令 CMD ["gunicorn", "--bind", "0.0.0.0:8000", "project.wsgi"]构建命令:
docker build -t my-django-app .3.2 Nginx配置
/etc/nginx/sites-available/myapp:
server { listen 80; server_name yourdomain.com; location /static/ { alias /var/www/static/; expires 30d; } location /media/ { alias /var/www/media/; expires 30d; } location / { proxy_pass http://localhost: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; } }启用配置:
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled sudo nginx -t # 测试配置 sudo systemctl restart nginx3.3 启动Docker容器
生产环境推荐使用docker-compose:
version: '3' services: web: image: my-django-app ports: - "8000:8000" volumes: - ./static:/var/www/static - ./media:/var/www/media restart: always启动命令:
docker-compose up -d4. 性能优化实践
4.1 Gunicorn配置优化
# gunicorn_config.py workers = (2 * cpu_count()) + 1 worker_class = 'gevent' keepalive = 60 timeout = 3004.2 Nginx缓存策略
# 静态资源缓存 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 365d; add_header Cache-Control "public, no-transform"; } # API接口禁用缓存 location /api/ { proxy_cache_bypass $http_cache_control; expires 0; add_header Cache-Control "no-cache"; }5. 安全加固措施
5.1 Docker安全
- 使用非root用户运行:
RUN useradd -m myuser USER myuser- 定期更新基础镜像
docker pull python:3.9-slim5.2 Nginx安全
- 隐藏版本信息:
server_tokens off;- 防止点击劫持:
add_header X-Frame-Options "SAMEORIGIN";6. 监控与维护
6.1 日志管理
查看容器日志:
docker logs -f container_nameNginx日志分析:
# 统计请求量前10的IP awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -n 106.2 资源监控
安装cAdvisor:
docker run \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:ro \ --volume=/sys:/sys:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \ --publish=8080:8080 \ --detach=true \ --name=cadvisor \ google/cadvisor:latest7. 常见问题解决方案
7.1 静态文件404错误
检查步骤:
- 确认Docker内执行了collectstatic
- 验证Nginx配置中的alias路径
- 检查文件权限:
sudo chown -R www-data:www-data /var/www/static7.2 数据库连接问题
典型症状:
- 容器重启后应用无法连接DB
- 高并发时出现连接池耗尽
解决方案:
- 使用连接池:
# settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'CONN_MAX_AGE': 600, ... } }- 容器网络配置:
# docker-compose.yml services: db: image: postgres:13 environment: POSTGRES_PASSWORD: mysecretpassword volumes: - postgres_data:/var/lib/postgresql/data web: depends_on: - db8. 高级部署方案
8.1 蓝绿部署实现
部署架构:
Nginx | /--------+--------\ v v blue_container green_container切换脚本示例:
# 切换流量到绿色环境 sed -i 's/blue_container/green_container/' /etc/nginx/sites-enabled/myapp nginx -s reload # 等待所有请求完成 sleep 60 # 停止蓝色环境 docker stop blue_container8.2 自动伸缩配置
使用Docker Swarm:
docker service create \ --name web \ --replicas 3 \ --publish published=8000,target=8000 \ my-django-app自动伸缩规则:
docker service update \ --replicas-max 10 \ --replicas-min 2 \ --update-parallelism 2 \ web9. 成本优化技巧
9.1 镜像瘦身
从原始镜像的1.2GB优化到180MB的方法:
# 多阶段构建 FROM python:3.9 as builder COPY requirements.txt . RUN pip install --user -r requirements.txt FROM python:3.9-slim COPY --from=builder /root/.local /root/.local ENV PATH=/root/.local/bin:$PATH9.2 资源限制
限制容器资源:
# docker-compose.yml services: web: deploy: resources: limits: cpus: '1' memory: 512M10. 本地开发与生产一致性
10.1 开发环境配置
docker-compose.override.yml:
version: '3' services: web: volumes: - .:/app ports: - "8000:8000" command: python manage.py runserver 0.0.0.0:800010.2 环境变量管理
使用.env文件:
# .env.production DJANGO_SETTINGS_MODULE=project.settings.production SECRET_KEY=your_production_keyDocker配置:
ENV DJANGO_SETTINGS_MODULE=project.settings.production启动时注入:
docker run --env-file .env.production my-django-app