jenkins 多阶段Dockefile -如何以正确的方式复制/安装依赖项

eh57zj3b  于 2023-02-15  发布在  Jenkins
关注(0)|答案(1)|浏览(179)

我使用Jenkins作业构建了一个带有多级Docker的python Web应用程序,在Jenkins作业的一个阶段,builder将所有deps安装到一个文件夹中(即pip install --target deps)。这些将被复制到Docker映像中,并具有相应的ENV PYTHONPATH=deps:.。但是,当我想启动PATH上的某个程序(例如uvicorn)时,错误消息是:sh uvicorn not found,当我用Python应用程序启动Docker映像时。我甚至将deps/bin添加到PATH中,但它仍然失败。我做错了什么?构建映像而不使用deps stage,只需安装一个venv就可以解决整个问题。
为了理解它,Makefile和Dockerfile的相关代码如下

FROM Python:3.9-slim as base
ENV  PYTHONPATH=deps:.

FROM base as builder 

RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,id=apt-lib,target=/var/lib/apt,sharing=locked \
    apt-get update && apt-get --no-install-recommends install -y build-essential

FROM base 

COPY deps deps
COPY app app

CMD [uvicorn, app.main:app, --host 0.0.0.0, --port 8000]

生成文件如下
x一个一个一个一个x一个一个二个x
项目结构草图如下所示

│   requirements.txt
├── app
│   ├── models
│   │   └── registry
│   ├── api_router.py
│   ├── configuration.py
│   ├── main.py
│   ├── schemas
│   │ 
│   └── tests
│       └── unit
└── docs

然而,仅仅将deps文件夹添加到ENV PYTHONPATH = deps:.并没有帮助。当提示pip list -v时,没有找到依赖项,但是对于pip freeze,它们被列出了。

uz75evzq

uz75evzq1#

这个Dockerfile有很多问题。
1.初始FROM行使用了错误的图像名称;如果您尝试从此Dockerfile构建映像,则会失败,并显示:

ERROR: failed to solve: failed to parse stage name "Python:3.9-slim":
invalid reference format: repository name must be lowercase

1.正如在评论中所讨论的,有一堆毫无意义的构建阶段,它们对构建过程没有任何贡献,可以被删除。
1.语法CMD [uvicorn, app.main:app, --host 0.0.0.0, --port 8000]不正确。尝试从该映像运行容器时,将失败,并显示:

/bin/sh: 1: [uvicorn,: not found

我们需要写它与适当的引用(见下文)。
1.因为你在容器 * 外部 * 安装依赖项,脚本(比如deps/bin/uvicorn)可能会有错误的Python解释器路径。
如果我们解决了上述所有问题,我们最终得到的Dockerfile如下所示:

FROM python:3.9-slim as base

ENV  PYTHONPATH=deps

COPY deps deps
COPY app app

# We call python3 explicitly here to deal with the fact that deps/bin/uvicorn
# probably has the wrong path to python3.
CMD ["python3", "./deps/bin/uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

如果我们从这个Dockerfile构建一个映像并运行它,它会工作:

$ docker build -t deps-example .
...
$ docker run --rm deps-example
INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

虽然上面的方法有效,但这并不是通常停靠Python应用程序的方式,更典型的设置是在容器内部安装依赖项(这将消除与路径相关的问题),例如,我们可以使用以下布局:

FROM python:3.9-slim as base

WORKDIR /app
COPY requirements.txt /app/
RUN pip install -r requirements.txt
COPY . /app/

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

相关问题