Skip to main content
 首页 » 编程设计

python之如何使用 pipenv 为 python 应用制作轻量级 docker 镜像

2024年08月13日33sharpest

我可以使用以下简单的 Dockerfile 为我的 python 应用生成工作图像:

FROM python:3.7 
WORKDIR /myapp 
COPY Pipfile* ./ 
RUN pip install pipenv 
RUN pipenv install --system --deploy 
COPY src . 
CMD ["python3", "app.py"] 

但是,它会生成约 1 GB 的镜像,其中可能包含临时文件,并且部署起来很繁重。而且我只需要用于构建目的的完整 python 图像。我的应用程序可以在 alpine 变体上成功运行,因此我可以生成两次 Dockerfile:

FROM python:3.7 as builder 
COPY Pipfile* ./ 
RUN pipenv lock --requirements > requirements.txt 
RUN python3 -m venv /venv 
RUN /venv/bin/pip install --upgrade pip 
RUN /venv/bin/pip install -r requirements.txt 
 
FROM python:3.7-alpine 
COPY --from=builder /venv /venv 
WORKDIR /myapp 
COPY src . 
CMD ["/venv/bin/python3", "app.py"] 

到目前为止一切顺利,它也可以工作,缩小了 6 倍。但是这个方案被认为是一些“ stub ”,有一些缺点:

  • 它有不必要的额外 COPY --from=builder 步骤
  • 它不使用 pipenv 但还需要 pip 进行安装(+1 额外步骤,pipenv lock+pip install 总是比 pipenv install) 慢
  • 它不会在系统范围内安装,而是安装在 /venv 中,应避免在容器内安装
  • 次要:构建会更多地污染中间图像缓存,并且需要下载两个图像变体。

如何结合这两种方法,使用 pipenv 获得基于 alpine 的轻量级图像,而没有提到的缺点?

或者您可以提供您的生产 Dockerfile 想法吗?

请您参考如下方法:

当您需要像 ciso8601 或一些需要构建过程的库时,问题就来了。构建工具并未“合并”到 slim 和 alpine 变体中,以实现较小的占用空间。

所以要安装 deps,你必须:

  • 安装构建工具
  • 在系统范围内从 Pipfile.lock 部署依赖项
  • 卸载构建工具并清理缓存

并在单个 RUN 层中执行这 3 个操作,如下所示:

FROM python:3.7-slim 
 
WORKDIR /app 
 
# both files are explicitly required! 
COPY Pipfile Pipfile.lock ./ 
 
RUN pip install pipenv && \ 
  apt-get update && \ 
  apt-get install -y --no-install-recommends gcc python3-dev libssl-dev && \ 
  pipenv install --deploy --system && \ 
  apt-get remove -y gcc python3-dev libssl-dev && \ 
  apt-get autoremove -y && \ 
  pip uninstall pipenv -y 
 
COPY app ./ 
 
CMD ["python", "app.py"] 
  • 操纵构建系统将花费您大约 300MiB 和一些额外的时间
  • 卸载 pipenv 可以再节省 20MiB(占最终大小的 10%)。
  • 分隔 RUN 命令不会从图层中删除数据,并且会生成约 500MiB 的图像。这是 Docker 的具体情况。

因此这将导致完美工作 ~200MiB 大小的图像,这是

  • 比原始 python:3.7 少 5 倍,(即 >1.0GiB)
  • 没有 alpine 不兼容(这些通常与 glibc 替换有关)

当时,我们可以接受 slim(debian buster)构建变体,更喜欢 slim 而不是 alpine(为了大多数兼容性)。如果你真的想进一步优化尺寸,我建议你看看这些家伙的一些优秀构建: