我使用 Poetry 进行依赖管理,并想构建一个 Docker 容器——我应该在 Docker 容器中运行 Poetry 吗?

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

我应该在 Docker 中运行 Poetry,还是应该使用 pip、pipx 或类似的东西?

我应该构建轮子或 tarball 并将它们传递到 Docker 容器中,而不是在 Docker 容器中运行 pip 或 poetry 吗?

这是我尝试过但从未开始工作的 Dockerfile 之一的示例 - 环境已损坏,我不知道为什么:

FROM python:3.10

# Configure Poetry
ENV POETRY_VERSION=1.2.0
ENV POETRY_HOME=/opt/poetry
ENV POETRY_VENV=/opt/poetry-venv
ENV POETRY_CACHE_DIR=/opt/.cache

# Install poetry separated from system interpreter
RUN python3 -m venv $POETRY_VENV \
    && $POETRY_VENV/bin/pip install -U pip setuptools \
    && $POETRY_VENV/bin/pip install poetry==${POETRY_VERSION}

# Add `poetry` to PATH
ENV PATH="${PATH}:${POETRY_VENV}/bin"

WORKDIR /app

# Install dependencies
COPY poetry.lock pyproject.toml ./
RUN poetry install

# Run your app
COPY . /app

ENTRYPOINT [ "./entrypoint.sh" ]

entrypoint.sh
包含:

poetry run blah

在这种情况下,问题是 virtualenv 坏了,我不知道为什么:

$ docker run blah/blah:latest
The virtual environment found in /app/.venv seems to be broken.
Recreating virtualenv blah-9TtSrW0h-py3.10 in /opt/.cache/virtualenvs/blah-9TtSrW0h-py3.10
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  ...
    import dateutil.parser
ModuleNotFoundError: No module named 'dateutil'

我什至应该在 Docker 中使用 Poetry 吗?我应该改用 pip 还是 pipx?

当你想在容器中运行 Python 应用程序时,你应该做什么?轮子是答案吗?还有别的答案吗?

docker python-packaging python-poetry
2个回答
2
投票

从错误中,

poetry
/app/.venv
中检测到一个虚拟环境,我猜你的应用程序没有
.dockerignore
从docker构建上下文中排除
.venv
,你本地的
.venv
也被
COPY . .
复制到图像中

您可以使用

poetry
在图像中安装依赖项,也可以使用
poetry
创建虚拟环境作为图像中的应用程序解释器,如下所示:

  1. poetry.toml
    ,是项目的
    poetry
    设置
[virtualenvs]
create = true # create virtual env when run poetry cmd
in-project = true # create .venv folder in project root dir for virtual env
  1. .dockerignore
.git
.venv
__pycache__
  1. Dockerfile
FROM python:3.10

# Add virtual env bin into PATH, use python of virtual env firstly
# Add virtual site-packages into PYTHONPATH, python can find module in it
ENV POETRY_VERSION=1.2.0 \
    PATH=/app/.venv/bin:${PATH} \
    PYTHONPATH=.:src:./.venv/lib/python3.10/site-packages:$PYTHONPATH

# Install poetry
RUN pip install poetry==${POETRY_VERSION}

WORKDIR /app

COPY . /app

# Install dependencies
RUN poetry install

ENTRYPOINT [ "./entrypoint.sh" ]

1
投票

我想出了一个似乎有效的方法:

  1. 用诗歌创建
    requirements.txt
    文件:
$ poetry export -f requirements.txt -o requirements.txt --without-hashes
  1. requirements.txt
    安装应用程序的依赖项,而不是使用 Poetry:
FROM python:3.10

WORKDIR /app
COPY . .

RUN pip install -r requirements.txt

ENTRYPOINT [ "./entrypoint.sh" ]

entrypoint.sh
包含:

#!/bin/bash
python3 -m blah.cli "$@"

为了确保我的

requirements.txt
poetry.lock
同步,我使用已简化为的 Makefile 构建容器:

VERSION := $(shell poetry version | cut -d ' ' -f 2)
CONTAINER_NAME := blah/blah

requirements:
    poetry export -f requirements.txt -o requirements.txt --without-hashes

container: requirements
    docker build -t $(CONTAINER_NAME):$(VERSION) -t $(CONTAINER_NAME):latest .

.PHONY: requirements container

当调用

poetry.lock
Makefile 目标时,这会在构建时将
requirements.txt
转换为
build
文件,并确保在构建容器映像时这两个文件同步。

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