buildx build --platform linux/amd64 通过诗歌显着增加图像大小

问题描述 投票:0回答:2

诗歌安装的软件包在为 amd64 构建时会显着增加图像大小。

我正在我的主机(MacOS、M2 Pro)上构建一个 docker 映像,我想将其部署到 EC2 实例。正常构建将使图像大小为 2GB,这很好。但部署在EC2上会导致系统兼容性问题:

WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64/v3) and no specific platform was requested
。所以我正在尝试使用
buildx
命令进行构建。然而,即使我更改的只是一个构建命令,它也会产生高达 13GB 的空间。我想知道为什么以及如何减小尺寸。

这是 Dockerfile:

FROM python:3.11-slim

# for -slim version (it breaks if you don't comment out && apt-get clean)
RUN apt-get update && apt-get install -y \
    gfortran \
    libopenblas-dev \
    liblapack-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Set environment variables to make Python and Poetry play nice
ENV POETRY_VERSION=1.7.1 \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    EXPERIMENT_ID=$EXPERIMENT_ID \
    RUN_ID=$RUN_ID


## Install poetry
RUN pip install "poetry==$POETRY_VERSION"

## copy project requirement files here to ensure they will be cached.
WORKDIR /app

COPY pyproject.toml ./

RUN poetry config virtualenvs.create false \
    && poetry install --no-interaction --no-dev --no-ansi  --verbose \
    && poetry cache clear pypi --all

使用这个 pyproject.toml,您可以重现构建。

[tool.poetry]
name = "malicious-url"
version = "0.1.0"
description = ""
authors = ["Makoto1021 <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.11"
numpy = "^1.26.4"
tld = "^0.13"
fuzzywuzzy = "^0.18.0"
scikit-learn = "^1.4.1.post1"
pandas = "^2.2.1"
mlflow = {extras = ["pipelines"], version = "^2.11.3"}
xgboost = "^2.0.3"
python-dotenv = "^1.0.1"
imblearn = "^0.0"
torch = "^2.2.2"
flask = "^3.0.3"
googlesearch-python = "^1.2.3"
whois = "^1.20240129.2"
nltk = "^3.8.1"

[tool.poetry.group.dev.dependencies]
ipykernel = "^6.29.3"
tldextract = "^5.1.2"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

这个命令将构建一个 2GB 的镜像。

docker build -f ./docker/Dockerfile \
-t malicious-url-prediction-img:v1 .

这将生成一个 13GB 的图像

docker buildx build --platform linux/amd64 -f ./docker/Dockerfile \
-t malicious-url-prediction-img:v1-amd64 .

如果删除 RUN 命令

poetry config virtualenvs.create...
,即使我为 amd64 构建映像,映像大小仍然很小。所以我认为诗歌造成了这个问题。然而,仅通过更改构建上下文就产生如此大的大小差异仍然很奇怪。

我使用

/bin/bash
du
命令进入巨大的图像,我发现总使用空间约为 2MB。因此,这表明大型 Docker 映像大小问题可能与我添加到映像中的文件没有直接关系,而是与基础映像以及包安装和配置创建的层直接相关。

我还使用

dive
来调查空间使用情况,但并没有真正说明问题所在。

我有一种感觉,它来自

poetry
有什么建议吗?

仅供参考,这就是我运行容器的方式。

docker run --rm -p 7070:5000 -v $(pwd)/logs:/app/logs malicious-url-prediction-img:v1-amd64

编辑:

  • 将 Dockerfile 更改为最小示例
  • 添加了 myproject.toml 来重现构建
  • 添加了我对诗歌的调查
python docker python-poetry
2个回答
0
投票

某些 ISA 可能会生成更小/更大的构建。但在你的情况下增加尺寸是不正常的。在这里,我建议对您的 Dockerfile 进行一次小重构。

我一直使用这个技巧,但我没有在这里测试。

您需要

gfortran
和其他一些包来构建您的 python 包。构建后,它们不是必需的,您可以卸载它们。

RUN apt install -y gfortran liblapack liblapack-dev libopenblas libopenblas-dev
RUN build your packages
RUN apt purge gfortran lapack-dev openblas-dev
RUN apt autoremove --purge
RUN other-cleanups

但是上面的代码不会减少你的docker镜像,因为构建依赖关系存在于上面的层中。您必须将上面的代码更改为:

RUN apt install -y gfortran liblapack liblapack-dev libopenblas libopenblas-dev ; \
    build your packages ; \
    apt purge gfortran lapack-dev openblas-dev ; \
    apt autoremove --purge

这将大大减小您的图像尺寸。

apt
pip
和 ...(默认情况下,
apt
会删除下载的
.deb
文件)下载缓存目录中的文件。您可以将
--mount=type=cache
添加到
RUN
参数中,以将它们缓存在单独的缓存卷中,而不是图像中。

所以这是你重构的

Dockerfile
(我添加了
liblapack
libopenblas
,所以它们必须留在
apt autoremove
之后):

FROM python:3.11-slim

ENV POETRY_VERSION=1.7.1 \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    EXPERIMENT_ID=$EXPERIMENT_ID \
    RUN_ID=$RUN_ID

WORKDIR /app
COPY poetry.lock pyproject.toml ./

RUN --mount=type=cache,target=/var/cache/apt \
    --mount=type=cache,target=/root/.cache/pip \
    --mount=type=cache,target=/root/.cache/pypoetry/cache \
    set -eux ; \
    apt update && apt install -y gfortran libopenblas libopenblas-dev liblapack liblapack-dev ; \
    pip install "poetry==$POETRY_VERSION" ; \
    poetry install --no-interaction --no-dev --no-ansi  --verbose ; \
    poetry cache clear pypi --all ; \
    apt purge gfortran libopenblas-dev liblapack-dev ; \
    apt autoremove --purge ; \
    rm -rf /var/lib/apt/lists/*

COPY mlartifacts/542535033067401306/2ba405d6d3144db6a5cd237509e53ef8 /app/mlartifacts/542535033067401306/2ba405d6d3144db6a5cd237509e53ef8/
COPY data/blacklist.txt data/whitelist.txt /app/data/
COPY *.py .
COPY utils/ ./utils/
COPY .env .

EXPOSE 7070

CMD ["poetry", "run", "flask", "run", "--host=0.0.0.0"]

-1
投票

问题在于构建。

当您运行 AMD64 时,可能已经有可以使用的预编译轮子,因此无需构建任何东西。当您使用 ARM64 时,可用的轮子通常会少很多,需要您构建项目。

构建占用空间 - 它们下载库、编译工件并将事物链接在一起。

您应该做的是使用多阶段构建。在构建过程的一个阶段运行安装,然后将创建的文件移至新容器中。

例如(这未经测试,但基于您的文件,并且应该进行一些调整):

FROM python:3.11-slim

# for -slim version (it breaks if you don't comment out && apt-get clean)
RUN apt-get update && apt-get install -y \
    gfortran \
    libopenblas-dev \
    liblapack-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Set environment variables to make Python and Poetry play nice
ENV POETRY_VERSION=1.7.1 \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    EXPERIMENT_ID=$EXPERIMENT_ID \
    RUN_ID=$RUN_ID


## Install poetry
RUN pip install "poetry==$POETRY_VERSION"

## copy project requirement files here to ensure they will be cached.
WORKDIR /app

COPY poetry.lock pyproject.toml ./

RUN poetry config virtualenvs.create false \
    && poetry install --no-interaction --no-dev --no-ansi  --verbose \
    && poetry cache clear pypi --all


# Build our actual container now.
FROM python:3.11-slim

ENV POETRY_VERSION=1.7.1 \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    EXPERIMENT_ID=$EXPERIMENT_ID \
    RUN_ID=$RUN_ID


# Copy all of the python files built in the Builder container into this smaller container.
COPY --from=Builder /usr/local/lib/python3.11 /usr/local/lib/python3.11

# Copy the model directory to the Docker image
COPY mlartifacts/542535033067401306/2ba405d6d3144db6a5cd237509e53ef8 /app/mlartifacts/542535033067401306/2ba405d6d3144db6a5cd237509e53ef8/

# Copy the blacklist and whitelist data
COPY data/blacklist.txt data/whitelist.txt /app/data/

## Copy Python files
COPY *.py .
COPY utils/ ./utils/
COPY .env .

EXPOSE 7070

CMD ["poetry", "run", "flask", "run", "--host=0.0.0.0"]

此方法用于所有 Multi-Py 项目(免责声明:我是这些项目的作者),因此您可以在那里查看示例。

© www.soinside.com 2019 - 2024. All rights reserved.