Python Web应用Docker+Nginx部署实战指南
1. Python Web应用部署方案概述
在2023年的开发现场,Docker+Nginx的组合已经成为Python Web应用部署的事实标准方案。这套方案之所以被广泛采用,关键在于它完美解决了传统部署中的三个痛点:环境不一致导致的"在我机器上能跑"问题、多应用端口管理混乱、以及HTTPS配置复杂。
我最近刚用这套方案部署了一个Flask电商项目,从测试环境到生产环境只用了不到15分钟。相比之前手动配环境、改配置的部署方式,效率提升了至少10倍。下面我就结合这个实战案例,拆解每个环节的技术细节和避坑要点。
2. 环境准备与工具选型
2.1 服务器基础配置
推荐使用Ubuntu 22.04 LTS作为基础系统,这是目前最稳定的生产环境选择。在阿里云/腾讯云购买实例时,注意勾选"自动安装Docker"选项,能省去后续安装步骤。最低配置建议:
- CPU:2核(动态页面多的选4核)
- 内存:4GB(Python应用内存占用较高)
- 系统盘:50GB SSD(Docker镜像很占空间)
重要提示:购买云服务器时一定要选择同一个地域的ECS和容器镜像服务,否则拉取镜像会产生流量费用。我曾经因为跨地域拉镜像一天被扣了200多块。
2.2 Docker环境配置
安装完Docker后需要立即做三件事:
- 配置镜像加速(国内直连Docker Hub慢到怀疑人生):
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
- 安装docker-compose:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
- 设置用户组(避免每次sudo):
sudo usermod -aG docker $USER
newgrp docker # 立即生效
2.3 Python项目结构调整
你的项目目录应该调整为以下结构(以Flask为例):
myapp/
├── app/ # 应用代码
│ ├── __init__.py
│ └── views.py
├── requirements.txt # 依赖文件
├── Dockerfile # 生产环境镜像
├── docker-compose.yml
└── nginx/
├── nginx.conf # 主配置
└── sites-enabled/ # 站点配置
关键点:requirements.txt必须精确指定版本号,否则后续构建可能失败。建议生成时使用:
pip freeze | grep -v "pkg-resources" > requirements.txt
3. Docker镜像构建实战
3.1 编写高效的Dockerfile
多阶段构建是必须掌握的技巧,能大幅减小最终镜像体积(我做的电商项目从1.2GB瘦身到180MB):
# 构建阶段
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 . .
# 确保脚本可执行
RUN chmod +x ./start.sh
ENV PATH=/root/.local/bin:$PATH
CMD ["./start.sh"]
几个优化点:
- 使用slim版本基础镜像
- 分离构建和运行环境
- 设置PATH让python命令可用
- 通过start.sh启动应用(方便注入环境变量)
3.2 镜像构建的坑与技巧
-
缓存利用:构建时按依赖变更频率排序COPY指令,把变动少的放前面。比如先COPY requirements.txt再COPY代码,这样修改代码时不会重复安装依赖。
-
国内加速:在Dockerfile最前面添加:
ENV PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
- 镜像瘦身:构建完成后运行以下命令清理无用层:
docker image prune --force --all
4. Nginx配置精要
4.1 反向代理配置
这是最简可用的Nginx配置(保存为nginx/sites-enabled/myapp.conf):
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://web:5000; # 这里的web是compose中的服务名
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 /app/static; # 静态文件直接由Nginx处理
expires 30d;
}
}
4.2 HTTPS自动配置
使用Let's Encrypt的certbot自动获取证书:
docker run -it --rm \
-v "/etc/letsencrypt:/etc/letsencrypt" \
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
-p 80:80 \
certbot/certbot certonly --standalone -d yourdomain.com
然后在nginx配置中添加:
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
5. 终极部署方案:docker-compose
完整的docker-compose.yml示例:
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- FLASK_ENV=production
restart: unless-stopped
volumes:
- ./app:/app # 开发时挂载代码实时更新
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx:/etc/nginx/conf.d
- /etc/letsencrypt:/etc/letsencrypt
depends_on:
- web
启动命令:
docker-compose up -d --build
6. 运维监控与问题排查
6.1 常用诊断命令
查看实时日志:
docker-compose logs -f --tail=100 web
进入容器调试:
docker exec -it myapp_web_1 bash
资源占用查看:
docker stats
6.2 性能优化参数
在docker-compose.yml中添加资源限制:
web:
deploy:
resources:
limits:
cpus: '2'
memory: 1G
reservations:
memory: 512M
6.3 备份与恢复
完整备份命令:
docker-compose exec db pg_dump -U postgres mydb > backup.sql # PostgreSQL示例
7. 高级技巧与扩展方案
7.1 蓝绿部署实践
通过标签实现零停机更新:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --scale web=3 --no-recreate
docker-compose exec nginx nginx -s reload
7.2 日志集中管理
在compose文件中添加:
services:
fluentd:
image: fluent/fluentd
volumes:
- ./logs:/fluentd/log
web:
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: myapp.web
7.3 自动伸缩配置
使用docker-swarm模式:
docker swarm init
docker service create --name web --replicas 3 -p 5000:5000 myapp_web
8. 踩坑记录与终极建议
- 时区问题:所有容器默认UTC时间,必须在Dockerfile中添加:
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
- 文件权限:容器内用户权限与宿主机冲突时,在docker-compose.yml中添加:
user: "${UID:-1000}:${GID:-1000}"
- 内存泄漏:Python应用建议在启动命令前加:
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--threads", "2", "app:app"]
最后分享一个监控脚本check_deploy.sh:
#!/bin/bash
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health)
if [ "$response" != "200" ]; then
docker-compose restart web
echo "$(date) - 检测到服务异常,已自动重启" >> /var/log/app_monitor.log
fi
更多推荐
所有评论(0)