你能给我一个Dockerfile的例子吗?我可以在其中安装所有我需要的软件包。锁定和pyproject。toml到我的镜像/容器从Docker?


当前回答

下面是一个剥离的例子,其中首先是一个带有依赖关系的层(仅在这些依赖关系发生变化时构建),然后将一个带有完整源代码的层添加到图像中。将poetry设置为安装到全局站点包中会留下一个配置工件,该配置工件也可以被删除。

FROM python:alpine

WORKDIR /app

COPY poetry.lock pyproject.toml ./
RUN pip install --no-cache-dir --upgrade pip \
 && pip install --no-cache-dir poetry \
 \
 && poetry config settings.virtualenvs.create false \
 && poetry install --no-dev \
 \
 && pip uninstall --yes poetry \

COPY . ./

其他回答

我的Dockerfile基于@lmiguelvargasf的回答。请参考他的帖子获得更详细的解释。我唯一的重大改变是以下几点:

我现在使用的是最新的官方安装程序install- poem .py,而不是官方文档中推荐的已弃用的get- poem .py。我还使用——version标志安装了一个特定的版本,但你也可以使用环境变量poeetry_version。更多关于他们官方文件的信息! 我使用的PATH是/root/。local/bin:$PATH而不是${PATH}:/root/。诗词/bin从OP的Dockerfile

FROM python:3.10.4-slim-buster

ENV PYTHONDONTWRITEBYTECODE 1 \
    PYTHONUNBUFFERED 1

RUN apt-get update \
    && apt-get install curl -y \
    && curl -sSL https://install.python-poetry.org | python - --version 1.1.13

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

WORKDIR /usr/app

COPY pyproject.toml poetry.lock ./

RUN poetry config virtualenvs.create false \
    && poetry install --no-dev --no-interaction --no-ansi

COPY ./src ./

EXPOSE 5000

CMD [ "poetry", "run", "gunicorn", "-b", "0.0.0.0:5000", "test_poetry.app:create_app()" ]

这是最适合我的最小配置:

FROM python:3.7

ENV PIP_DISABLE_PIP_VERSION_CHECK=on

RUN pip install poetry

WORKDIR /app
COPY poetry.lock pyproject.toml /app/

RUN poetry config virtualenvs.create false
RUN poetry install --no-interaction

COPY . /app

注意,它不像@sobolevn的配置那样安全。

作为一个小问题,我将补充一下pyproject是否可以进行可编辑安装。Toml项目,可以删除一两行:

FROM python:3.7

ENV PIP_DISABLE_PIP_VERSION_CHECK=on

WORKDIR /app
COPY poetry.lock pyproject.toml /app/

RUN pip install -e .

COPY . /app

在将诗歌与docker一起使用时,有几件事需要记住。

安装

安装诗歌的官方方式是:

curl -sSL https://install.python-poetry.org | python3 -

这种方式允许诗歌及其依赖从你的依赖中分离出来。但是,在我看来,这不是一件很好的事情,有两个原因:

诗歌版本可能会得到更新,它会破坏你的构建。在这种情况下,您可以指定poeetry_version环境变量。安装程序将尊重它 我不喜欢在没有任何保护措施的情况下,将来自互联网的文件传输到我的容器中

所以,我使用pip安装'poetry==$ poeetry_version '。如您所见,我仍然建议固定您的版本。

另外,把这个版本固定在pyproject中。Toml也是:

[build-system]
# Should be the same as `$POETRY_VERSION`:
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

它将保护您避免本地和docker环境之间的版本不匹配。

缓存的依赖关系

我们想要缓存我们的需求,并且只在pyproject时重新安装它们。汤姆或诗歌。锁定文件更改。否则构建会很慢。为了实现工作缓存层,我们应该放:

COPY poetry.lock pyproject.toml /code/

在安装诗词之后,但在添加任何其他文件之前。

Virtualenv

接下来要记住的是virtualenv创建。我们在docker中不需要它。它已经被孤立了。因此,我们使用诗意配置virtualenvs。创建假设置关闭它。

开发vs生产

如果你像我一样使用相同的Dockerfile进行开发和生产,你将需要根据一些环境变量安装不同的依赖集:

poetry install $(test "$YOUR_ENV" == production && echo "--no-dev")

通过这种方式,$YOUR_ENV将控制将安装哪些依赖集:all(默认)或仅生产带有——no-dev标志。

你可能还想添加一些更好的体验选项:

——无互动不要问任何互动问题 ——no-ansi标志,使您的输出更日志友好

结果

你会得到类似的结果:

FROM python:3.6.6-alpine3.7

ARG YOUR_ENV

ENV YOUR_ENV=${YOUR_ENV} \
  PYTHONFAULTHANDLER=1 \
  PYTHONUNBUFFERED=1 \
  PYTHONHASHSEED=random \
  PIP_NO_CACHE_DIR=off \
  PIP_DISABLE_PIP_VERSION_CHECK=on \
  PIP_DEFAULT_TIMEOUT=100 \
  POETRY_VERSION=1.0.0

# System deps:
RUN pip install "poetry==$POETRY_VERSION"

# Copy only requirements to cache them in docker layer
WORKDIR /code
COPY poetry.lock pyproject.toml /code/

# Project initialization:
RUN poetry config virtualenvs.create false \
  && poetry install $(test "$YOUR_ENV" == production && echo "--no-dev") --no-interaction --no-ansi

# Creating folders, and files for a project:
COPY . /code

你可以在这里找到一个真实的例子:weakake -django-template

2019年12月17日更新

将诗歌更新到1.0

2022-11-24更新

更新curl命令使用现代诗歌安装脚本

多阶段Docker构建与诗歌和venv

不要禁用virtualenv创建功能。virtualenv在Docker构建中发挥了作用,因为它们提供了一种优雅的方式来利用多阶段构建。简而言之,构建阶段将所有内容安装到virtualenv中,而最后阶段只是将virtualenv复制到一个小映像中。

在复制代码之前,先使用诗歌导出并安装固定的需求。这将允许您使用Docker构建缓存,并且永远不会因为更改代码中的一行而重新安装依赖项。

不要使用诗意安装来安装代码,因为它将执行可编辑的安装。相反,使用诗歌构建来构建一个轮子,然后将其安装到您的virtualenv中。(感谢PEP 517,这整个过程也可以通过简单的pip install .来执行,但由于构建隔离,您最终将安装另一个Poetry副本。)

下面是一个Dockerfile安装Flask应用到Alpine镜像的例子,它依赖于Postgres。本例使用入口点脚本激活virtualenv。但一般来说,没有入口点脚本也没问题,因为您可以在CMD指令中简单地引用/venv/bin/ Python的Python二进制文件。

Dockerfile

FROM python:3.7.6-alpine3.11 as base

ENV PYTHONFAULTHANDLER=1 \
    PYTHONHASHSEED=random \
    PYTHONUNBUFFERED=1

WORKDIR /app

FROM base as builder

ENV PIP_DEFAULT_TIMEOUT=100 \
    PIP_DISABLE_PIP_VERSION_CHECK=1 \
    PIP_NO_CACHE_DIR=1 \
    POETRY_VERSION=1.0.5

RUN apk add --no-cache gcc libffi-dev musl-dev postgresql-dev
RUN pip install "poetry==$POETRY_VERSION"
RUN python -m venv /venv

COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt | /venv/bin/pip install -r /dev/stdin

COPY . .
RUN poetry build && /venv/bin/pip install dist/*.whl

FROM base as final

RUN apk add --no-cache libffi libpq
COPY --from=builder /venv /venv
COPY docker-entrypoint.sh wsgi.py ./
CMD ["./docker-entrypoint.sh"]

docker-entrypoint.sh

#!/bin/sh

set -e

. /venv/bin/activate

while ! flask db upgrade
do
     echo "Retry..."
     sleep 1
done

exec gunicorn --bind 0.0.0.0:5000 --forwarded-allow-ips='*' wsgi:app

wsgi.py

import your_app

app = your_app.create_app()

使用docker多阶段构建和python slim image,将诗词锁导出到requirements.txt,然后在virtualenv中通过pip安装。

它有最小的尺寸,不需要诗在运行时的形象,钉的版本一切。

FROM python:3.9.7 as base
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app

FROM base as poetry
RUN pip install poetry==1.1.12
COPY poetry.lock pyproject.toml /app/
RUN poetry export -o requirements.txt

FROM base as build
COPY --from=poetry /app/requirements.txt /tmp/requirements.txt
RUN python -m venv .venv && \
    .venv/bin/pip install 'wheel==0.36.2' && \
    .venv/bin/pip install -r /tmp/requirements.txt

FROM python:3.9.7-slim as runtime
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
ENV PATH=/app/.venv/bin:$PATH
COPY --from=build /app/.venv /app/.venv
COPY . /app