生产环境部署 Django 项目时,Dockerfile 应基于官方 Python slim 镜像,安装系统编译依赖后安装 Python 包,并使用 Gunicorn 或 uWSGI 替代开发服务器启动应用。关键风险在于不要在容器内直接运行 runserver 生产流量,且需处理好静态文件收集与数据库迁移时机。
先说结论:使用单层 slim 镜像或多阶段构建均可,核心是分离依赖安装与代码复制,确保生产服务器非开发模式。
- 适合:Web 服务容器化、CI/CD 自动化部署、多环境一致性管理
- 先准备:requirements.txt 文件、系统依赖清单、生产级 WSGI 服务器配置
- 验收:容器启动日志无报错、健康检查接口返回 200、静态文件可访问
命令速用版
以下 Dockerfile 模板适用于大多数 Django 项目,基于 Python 3.11 slim 镜像,包含系统依赖安装与 Gunicorn 启动配置。
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y gcc libpq-dev && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install `--no-cache-dir` -r requirements.txt
COPY . .
RUN python manage.py collectstatic `--noinput`
ENV PYTHONUNBUFFERED=1
CMD ["gunicorn", "`--bind`", "0.0.0.0:8000", "your_project.wsgi"]
为什么会这样
Docker 容器化核心目的是环境一致性,避免开发环境与生产环境依赖冲突。Django 默认开发服务器 runserver 单线程且未优化,不适合生产流量,必须使用 Gunicorn 或 uWSGI 等 WSGI 服务器。系统级依赖如 gcc 和 libpq-dev 用于编译 Python 扩展包,缺少会导致 pip install 失败。静态文件必须在构建阶段收集到指定目录,否则 Nginx 无法代理。
分步处理
步骤 1:选择基础镜像
使用官方 python:3.11-slim 镜像,体积较小且包含必要运行时。避免使用 latest 标签,固定版本可防止意外更新导致兼容性问题。
步骤 2:安装系统依赖
在 pip install 之前运行 apt-get 安装编译工具。常见依赖包括 gcc、libpq-dev(PostgreSQL)、default-libmysqlclient-dev(MySQL)。安装后清理 apt 缓存减小镜像体积。
步骤 3:安装 Python 依赖
先复制 requirements.txt 再运行 pip install。利用 Docker 缓存层,若依赖未变动则跳过此步加速构建。添加 `--no-cache-dir` 参数避免缓存文件占用空间。
步骤 4:复制代码与收集静态文件
复制项目代码后执行 python manage.py collectstatic。确保 settings.py 中 STATIC_ROOT 已配置,否则命令会报错。此步骤需在容器构建时完成,而非运行时。
步骤 5:配置启动命令
使用 CMD 或 ENTRYPOINT 启动 Gunicorn。绑定 0.0.0.0 端口以便外部访问。设置 ENV PYTHONUNBUFFERED=1 确保日志实时输出到 stdout,方便 docker logs 查看。
怎么验证是否生效
构建验证:运行 docker build -t django-app . 观察是否有报错,确认各层缓存命中情况。
运行验证:执行 docker run -p 8000:8000 django-app,检查容器状态是否为 Up。
日志检查:使用 docker logs <container_id> 查看启动日志,确认 Gunicorn worker 启动成功且无 ImportError。
功能检查:访问 http://localhost:8000/admin/ 确认页面加载正常,静态文件 CSS/JS 无 404 错误。
常见坑
开发服务器误用:切勿在生产 Dockerfile 中使用 python manage.py runserver。该服务器仅用于开发,性能差且不安全。
数据库迁移时机:迁移命令 manage.py migrate 建议在容器启动入口脚本中执行,而非 Dockerfile 构建阶段。构建阶段无法连接生产数据库,且每次代码变更都构建镜像会导致效率低下。
静态文件权限:collectstatic 收集的文件夹需确保 Nginx 容器有读取权限。若使用多容器架构,需通过 volume 挂载共享静态文件目录。
系统依赖缺失:若 requirements.txt 包含 psycopg2 或 mysqlclient,未安装 libpq-dev 或 gcc 会导致编译失败。报错信息通常包含 error: command 'gcc' failed。
常见问题
数据库迁移命令放在哪里执行?
建议放在容器启动脚本中,而非 Dockerfile 里。构建镜像时无法连接数据库,且每次构建都迁移会导致生产环境不可控。可在 docker-compose 的 command 或 entrypoint 脚本中先执行 migrate 再启动服务。
静态文件收集后找不到怎么办?
检查 settings.py 中 STATIC_ROOT 路径是否与 collectstatic 输出一致。若使用 Nginx 容器,需通过 volume 将 Django 容器的静态目录挂载到 Nginx 容器的 html 目录。
Gunicorn 和 uWSGI 选哪个?
两者均为成熟 WSGI 服务器。Gunicorn 配置简单,适合大多数场景;uWSGI 功能更丰富但配置复杂。若项目无特殊需求,推荐优先使用 Gunicorn 减少维护成本。
参考来源
- 搜索来源:Django-Constance 部署实战:5 个步骤实现 Docker 容器化与生产环境配置终极指南
- 搜索来源:Django+Docker 部署最佳实践:基于 docker-django-example 的完整 CI/CD 流程
- 搜索来源:使用 Docker 容器化部署 Django 项目:从零开始的最佳实践指南
- 搜索来源:【Docker 实战】将 Django 应用容器化的完整指南
- 搜索来源:Docker 部署 Django 的详细指南