首页 > 解决方案 > 使用多阶段 Dockerfile,pip 轮仍然需要来自基础构建器的依赖项

问题描述

我是 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

标签: pythondjangodockerdockerfile

解决方案


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

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

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

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

..
COPY --from=builder /root/.local /home/.local
..

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

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

ENV PATH=/root/.local/bin:$PATH

推荐阅读