Docker 部署 Django 项目如何配置多阶段构建减小镜像体积?

文章导读
在 Docker 部署 Django 项目时,使用多阶段构建(Multi-stage Builds)将编译环境与运行环境分离,是减小镜像体积最通用且有效的方案,尤其适合需要安装含 C 扩展依赖的生产场景。
📋 目录
  1. 完整 Dockerfile 示例
  2. .dockerignore 配置指南
  3. 依赖管理建议
  4. 验证构建结果
  5. 常见风险与排查
A A

在 Docker 部署 Django 项目时,使用多阶段构建(Multi-stage Builds)将编译环境与运行环境分离,是减小镜像体积最通用且有效的方案,尤其适合需要安装含 C 扩展依赖的生产场景。

先说结论:多阶段构建能通过丢弃构建工具链和临时文件,显著降低最终镜像体积,但需注意依赖兼容性、静态文件收集及容器安全权限。

  • 适合:生产环境部署、需要编译 Python 扩展库(如 psycopg2、Pillow)的项目。
  • 先准备:梳理 requirements.txt,区分运行时依赖与构建时依赖,确认基础镜像版本一致。
  • 验收:构建完成后对比镜像大小,检查容器内是否无构建工具且服务正常启动,确认非 root 用户运行。

完整 Dockerfile 示例

以下配置修正了语法错误,增加了非 root 用户运行支持,并处理了静态文件收集的环境变量问题。请将 project 替换为你的实际 Django 项目名。

FROM python:3.9-slim as builder

WORKDIR /app

# 安装构建依赖,注意参数前无需反引号
RUN apt-get update && apt-get install -y `--no-install-recommends` gcc python3-dev

COPY requirements.txt .
# 使用 `--user` 安装到用户目录,方便后续复制
RUN pip install `--user` `--no-cache-dir` -r requirements.txt

FROM python:3.9-slim

WORKDIR /app

# 复制构建阶段安装的 Python 包
COPY `--from`=builder /root/.local /root/.local

# 复制项目代码
COPY . .

# 配置环境变量
ENV PATH=/root/.local/bin:$PATH
ENV DJANGO_SETTINGS_MODULE=project.settings
ENV PYTHONUNBUFFERED=1

# 收集静态文件
RUN python manage.py collectstatic `--noinput`

# 创建非 root 用户并授权
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# 启动服务,注意 wsgi 入口格式
CMD ["gunicorn", "`--bind`", "0.0.0.0:8000", "project.wsgi:application"]

.dockerignore 配置指南

构建镜像前,务必在项目根目录创建 .dockerignore 文件,排除不必要的文件,避免构建上下文过大导致构建缓慢或镜像体积虚高。

Docker 部署 Django 项目如何配置多阶段构建减小镜像体积?
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env
venv
.venv
.git
.gitignore
.DS_Store
.db.sqlite3
staticfiles
*.log
.env

依赖管理建议

requirements.txt 中明确指定版本,避免构建环境与实际环境不一致。对于需要编译的库,确保构建阶段安装了相应的系统依赖(如 libjpeg-dev 对应 Pillow)。

Django==4.2.0
gunicorn==21.2.0
psycopg2-binary==2.9.6
Pillow==10.0.0

验证构建结果

1. 查看镜像大小
使用 docker images 命令查看构建前后的镜像大小差异。多阶段构建通常能去掉几百兆的构建工具。

2. 检查容器内部
运行以下命令进入容器,确认构建工具已移除且用户权限正确:

Docker 部署 Django 项目如何配置多阶段构建减小镜像体积?
docker run -it `--rm` <镜像名> bash
# 在容器内执行
which gcc  # 应返回空或 command not found
id         # 应显示 uid=1000(appuser)

3. 功能测试
访问 Django 项目页面,确认静态文件加载正常,数据库连接正常,没有 ImportError 报错。

常见风险与排查

1. 系统库缺失
运行阶段如果缺少某些系统库(如 libjpeg 用于 Pillow),即使 Python 包复制过来了也会报错。需要在运行阶段的 Dockerfile 中也安装必要的运行时系统库(无需 gcc)。

Docker 部署 Django 项目如何配置多阶段构建减小镜像体积?

2. 基础镜像版本不一致
构建阶段和运行阶段的基础镜像版本必须一致(如都用 python:3.9-slim),否则编译好的二进制文件可能因 glibc 版本不同而无法运行。

3. 权限问题
切换非 root 用户后,确保该用户对静态文件目录和日志目录有写入权限。如有必要,在 USER 指令前调整 chown 范围。

4. 静态文件未收集
如果忘记运行 collectstatic 或缺少 DJANGO_SETTINGS_MODULE 环境变量,生产环境可能无法加载 CSS 和 JS 文件。确保该命令在构建流程中执行且环境变量已设置。