python - 使用多阶段 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
解决方案
好的,花了几个小时后,我发现了问题并修复了它。所以我会回答我自己的问题。
首先,我在命令中使用--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
推荐阅读
- reactjs - 使用 React defaultProps 正确设置 prop 的初始状态
- python - 从 CharField 更改为 IntegerField - Postgres 列数据类型未更改 Django
- c# - xamarin 'Forms.Context' 已过时:'从 2.5 版开始,上下文已过时。请改用本地上下文。
- kubernetes - 遇到错误,我不理解 k8s
- java - 如何使用 selenium 模拟人类滚动弹出对话框?
- cuda - 安装cuda后显卡驱动失败
- c - C语言中的位运算
- sql - 在数据库中保存其他 ID
- java - 我想知道为什么我得到 L 的地址而不是值?
- wordpress - wordpress 更新时后端出错