27-Docker部署Django(上)-从2GB到180MB的镜像瘦身实战

文章目录

  • [Docker 部署 Django(上):从"这个镜像为什么这么大"到多阶段构建](#Docker 部署 Django(上):从"这个镜像为什么这么大"到多阶段构建)
    • 导入语
    • [1 ~> 镜像大小对比------从 2GB 到 180MB 的路径](#1 ~> 镜像大小对比——从 2GB 到 180MB 的路径)
    • [2 ~> 版本一:从基础镜像开始------1100MB 起步](#2 ~> 版本一:从基础镜像开始——1100MB 起步)
    • [3 ~> 版本二:换成 `slim` 镜像------450MB](#3 ~> 版本二:换成 slim 镜像——450MB)
    • [4 ~> 版本三:清理 pip 缓存------350MB](#4 ~> 版本三:清理 pip 缓存——350MB)
    • [5 ~> 版本四:多阶段构建------210MB(质变)](#5 ~> 版本四:多阶段构建——210MB(质变))
    • [6 ~> `alpine` 的陷阱------pycryptodome 和其他 musl 不兼容问题](#6 ~> alpine 的陷阱——pycryptodome 和其他 musl 不兼容问题)
    • [思考 && 总结](#思考 && 总结)
    • 结尾

Docker 部署 Django(上):从"这个镜像为什么这么大"到多阶段构建

📖 文章简介: 把 Django 项目 Docker 化的第一步------写 Dockerfile。但大多数人第一次构建出来的镜像都在 800MB-1.2GB 之间。原因很简单:基础镜像选了 python:3.11 而不是 python:3.11-slim,构建依赖和运行依赖混在一起,pip install 的缓存文件没清理。上篇聚焦 Dockerfile 的优化------从单阶段构建到多阶段构建、从 pip install--no-cache-dir、从盲目选镜像到理解 slimalpine 的 musl libc 兼容性。配有一个 Django 项目从 950MB 瘦身到 180MB 的完整优化过程。


🎬 个人主页: 源码骑士

专栏传送门: 《Android开发基础》《python基础课程》

⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂


🎬 源码骑士的简介:

5年Android Framework系统开发经验,曾主导多项系统级性能优化专项

技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)

累计产出原创技术文章100+篇,文章以源码拆解为特色,被读者评价为"看一篇胜过啃一周文档"


导入语

第一次把 Django 项目 Docker 化,我写了这样一个 Dockerfile:

dockerfile 复制代码
FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

构建完后 docker images 显示 2.1GB。我以为是 Docker 的问题,查了之后才发现 python:3.11 基础镜像就 1GB------它包含了完整的 Debian 系统加 Python 加编译工具链,全塞进一个镜像。而我的 Django 项目本身只有 8MB。

上篇带你从 2.1GB 的巨型镜像一路优化到 180MB。下篇讲 docker-compose 编排 Django + MySQL + Redis。


1 ~> 镜像大小对比------从 2GB 到 180MB 的路径

Dockerfile 版本 镜像大小 改进点
FROM python:3.11 2.1 GB 基础镜像
FROM python:3.11-slim 450 MB 换成 slim 版(去掉编译工具)
+ pip --no-cache-dir 350 MB 清理缓存
+ 多阶段构建 210 MB 分离构建工具和运行依赖
+ .dockerignore 180 MB 排除不必要的文件

2 ~> 版本一:从基础镜像开始------1100MB 起步

dockerfile 复制代码
FROM python:3.11     # 1GB 的基础镜像
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt    # pip 缓存又加几百兆
COPY . .
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

问题:python:3.11 包含编译器、开发库、deb 包管理、git、curl...... Django 运行起来只需要 Python 解释器和你的代码。你不需要 gcc。


3 ~> 版本二:换成 slim 镜像------450MB

dockerfile 复制代码
FROM python:3.11-slim    # 只有 120MB 的基础镜像

slim = 去掉开发工具的 Debian 精简版。它不装 gcc、不装 git,但仍然保留了 apt-get 和足够多的系统库能装 Python 包。


4 ~> 版本三:清理 pip 缓存------350MB

dockerfile 复制代码
RUN pip install --no-cache-dir -r requirements.txt

加上 --no-cache-dir,pip 不会在镜像里保存下载的 wheel 文件。又省几十 MB。


5 ~> 版本四:多阶段构建------210MB(质变)

dockerfile 复制代码
# 第一阶段:构建------有编译器
FROM python:3.11-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends gcc
RUN pip install --user --no-cache-dir -r requirements.txt

# 第二阶段:运行------只有必需的东西
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

核心思想: 用第一阶段装 gcc、编译 C 扩展(如 mysqlclient),但第二阶段不包含 gcc------只拷贝运行所需的东西。最后镜像里没有编译器。


6 ~> alpine 的陷阱------pycryptodome 和其他 musl 不兼容问题

很多教程推荐 python:3.11-alpine(只有 50MB)。但它使用 musl libc 而非 glibc。某些 Python 包(尤其是 C 扩展的 wheel 只提供 glibc 版本)无法在 Alpine 上跑:

bash 复制代码
ImportError: Error loading shared library ld-linux-x86-64.so.2

除非你确认所有依赖有 musl 兼容的 wheel,否则先用 slim slim 基于 Debian + glibc,兼容性最高。


思考 && 总结

Dockerfile 优化三步骤:

  1. slimalpine 替代默认镜像------基础大小从 1GB 降到 120MB。
  2. 多阶段构建------构建阶段装编译器,运行阶段只拷贝结果------镜像里没有 gcc。
  3. .dockerignore 排除 venv/__pycache__/.git/------这些文件不需要在容器里。

结尾

上篇到这里结束。下篇讲 docker-compose.yml 编排------Django + MySQL + Redis + Nginx 一站式部署。

源码骑士 --- 源码级拆解,从底层看透技术

👀 关注:跟博主一起从源码视角深耕底层原理

❤️ 点赞:让优质内容被更多人看见

收藏:核心知识点存好,随用随查

💬 评论:分享你的经验或疑问,一起交流

🔄 一键四连:别忘了给博主一键四连!

🗡️ 寄语:Docker 镜像瘦身不是炫技------小镜像 = 快部署 = 小攻击面。

结语:210MB 的生产镜像,部署从 60 秒降到 8 秒。瘦身是值得的。一键四连!

相关推荐
xsc-xyc1 小时前
CasaOS + Docker 挂载外接硬盘部署 Jellyfin 私人影院
运维·docker·容器
日取其半万世不竭1 小时前
PostgreSQL 跑在 Docker 里怎么备份?恢复成功才算备份成功
数据库·docker·postgresql
至此流年莫相忘1 小时前
WSL2 下 Docker Desktop 完全配置指南:从安装到极速体验
运维·docker·容器
杰杰7981 小时前
DRF的分页讲解-入门篇 三个基础分页类介绍
python·django
万能的知了2 小时前
K8s到底需不需要GPU节点?集群资源分配的底层逻辑
云原生·容器·kubernetes
极客先躯2 小时前
高级java每日一道面试题-2026年02月12日-实战篇[Docker]-什么是容器的 Seccomp 配置?如何自定义?
java·运维·分布式·docker·容器·自动化·文件
王小王-1232 小时前
基于电脑硬件市场数据分析与可视化系统
数据库·数据分析·django·sqlite·电脑·电脑硬件数据·电脑硬件市场分析
码云骑士2 小时前
25-数据库连接池-Django连接复用与连接数上限控制
数据库·python·django
码云骑士2 小时前
22-接手Django老项目(下)-读懂urls路由树与架构脉络
python·架构·django