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

How to make lightweight docker image for python app with pipenv

我可以使用以下简单的 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",有一些缺点:


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

或者您可以提供您的制作 Dockerfile 想法吗?

怎么样,

FROM python:3.7-alpine

WORKDIR /myapp

COPY Pipfile* ./

RUN pip install --no-cache-dir pipenv && \
    pipenv install --system --deploy --clear

COPY src .
CMD ["python3", "app.py"]
  1. 它使用较小的 Alpine 版本。
  2. 使用 --no-cache-dir 选项 pip--clear 选项 pipenv,您不会留下任何不必要的缓存文件。
  3. 您还部署在 venv 之外。

您还可以在同一 RUN 命令中的 pipenv install --system --deploy --clear 之后添加 && pip uninstall pipenv -y 以消除 pipenv 拍摄的 space 如果额外的图像尺寸困扰您.

当您需要 ciso8601 或某些需要构建过程的库时,问题就来了。构建工具未 "incorporated" 到 slimalpine 变体中,以实现较小的占用空间。

因此,要安装 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(为了大多数兼容性)。如果你真的想进一步优化尺寸,我建议你看看这些家伙的一些优秀构建:

我正在使用 micropipenv 进行作业,它自称是

A lightweight wrapper for pip to support requirements.txt, Pipenv and Poetry lock files or converting them to pip-tools compatible output. Designed for containerized Python applications but not limited to them.

从中创建的图像如下所示。 由于 alpine 基础图像缺少 toml 解析器,我们必须使用包含 toml 附加功能的 micropipenv 版本(micropipenv[toml] 而不是 micropipenv)。

FROM python:3.9-alpine

WORKDIR /myapp
COPY Pipfile Pipfile.lock ./

RUN \
  # Install dependencies
  && pip install --no-cache-dir micropipenv[toml] \
  && micropipenv install --deploy \
  && pip uninstall -y micropipenv[toml]

COPY src .
CMD ["python3", "app.py"]