使用多阶段 Dockerfile,pip 轮仍然需要来自基础构建器的依赖项

koz*_*rin 2 python django docker dockerfile

我是 Docker 环境的新手。所以,很抱歉,如果问这个问题很常见。

我使用下面的 Dockerfile,它首先使用构建器来使用轮子进行构建。问题是我的requirements.txt 文件中的加密包(pip 包)需要gcc 和其他一些包来构建。如下所示,我RUN apk add在基础构建器中安装了这些软件包(gcc 和其他软件包),然后构建了轮子。然而,在最终的构建器中,我收到错误消息“gcc:没有这样的文件...”,这意味着 gcc 尚未安装。(但我使用的是基础构建器生成的轮子!为什么它仍然需要 gcc 和其他东西?)

如果我也在最终构建中安装 gcc 和其他构建依赖项,那么它会再次解决问题,是的。但是,在这种情况下,我失去了使用多阶段 Dockerfile 的好处。

我不明白这个问题。你能帮助我吗?

这是 Dockerfile:

FROM python:3.9.1-alpine as builder

WORKDIR /usr/src/MYAPP

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt .

RUN apk update \
    && apk add --virtual build-deps gcc python3-dev musl-dev \
        libressl-dev libffi-dev cargo \
    && apk add postgresql-dev \
    && apk add jpeg-dev zlib-dev libjpeg \
    && pip install --upgrade pip \
    && pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/MYAPP/wheels -r requirements.txt \
    && apk del build-deps

RUN pip install flake8
COPY . .
RUN flake8 --ignore=E501,F401 .


############
############
### FINAL ##
############
############
FROM python:3.9.1-alpine

RUN mkdir -p /home/MYAPP

RUN addgroup -S MYAPP && adduser -S MYAPP -G MYAPP

# create the appropriate directories
ENV HOME=/home/MYAPP
ENV APP_HOME=/home/MYAPP/web
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

# install dependencies
RUN apk add libpq
COPY --from=builder /usr/src/MYAPP/wheels /wheels
COPY --from=builder /usr/src/MYAPP/requirements.txt .
RUN pip install --no-cache /wheels/*

COPY . $APP_HOME

RUN chown -R MYAPP:MYAPP $APP_HOME

USER MYAPP
Run Code Online (Sandbox Code Playgroud)

koz*_*rin 7

好的,花了几个小时后,我发现了问题并解决了它。所以我会回答我自己的问题。

首先,我在命令--no-deps中使用了参数pip wheel。该参数导致 pipwheel 只下载主包,而不下载它们的依赖项。因此,在第二个构建映像(阶段)中,pip 尝试下载这些主要依赖项的所有子依赖项。因此,这些依赖项需要一些系统包来构建。

删除此--no-deps参数通常可以解决这种情况下的问题,但它会导致我的情况出现另一个错误。依赖项之间存在一些版本冲突,而常规pip install -r ...

pip wheel我没有使用该技术,而是使用pip install --user -r选项将我的需求安装在文件夹中/root/.local。然后我将/root/.local文件夹移动到第二阶段的/root:

..
COPY --from=builder /root/.local /home/.local
..
Run Code Online (Sandbox Code Playgroud)

就这样。我的所有要求也都安装在第二个构建映像中。

不要忘记将 /root/.local/bin 路径添加到您的$PATH

ENV PATH=/root/.local/bin:$PATH
Run Code Online (Sandbox Code Playgroud)