你能给我的例子Dockerfile
中,我可以安装我从需要的所有包poetry.lock
,并pyproject.toml
为从泊坞我的形象/容器?
你能给我的例子Dockerfile
中,我可以安装我从需要的所有包poetry.lock
,并pyproject.toml
为从泊坞我的形象/容器?
Answers:
poetry
与一起使用时,要记住几件事docker
。
官方安装方式poetry
是通过:
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
这种方式允许将poetry
其依赖项与您的依赖项隔离。但是,在我看来,这并不是一件好事,原因有两个:
poetry
版本可能会得到更新,这会破坏您的构建。在这种情况下,您可以指定POETRY_VERSION
环境变量。安装程序将尊重它因此,我使用pip install 'poetry==$POETRY_VERSION'
。如您所见,我仍然建议固定您的版本。
另外,还要将此版本固定在您的计算机pyproject.toml
中:
[build-system]
# Should be the same as `$POETRY_VERSION`:
requires = ["poetry>=1.0"]
build-backend = "poetry.masonry.api"
它将防止本地和docker
环境之间的版本不匹配。
我们希望缓存我们的要求,仅在pyproject.toml
或poetry.lock
文件更改时重新安装它们。否则构建速度会很慢。为了实现工作缓存层,我们应该放置:
COPY poetry.lock pyproject.toml /code/
在后poetry
安装,但在此之前添加任何其他文件。
接下来要记住的是virtualenv
创造。我们不需要它docker
。它已经被隔离。因此,我们使用poetry config virtualenvs.create false
设置将其关闭。
如果Dockerfile
像我一样在开发和生产中都使用相同的代码,则需要根据一些环境变量安装不同的依赖项集:
poetry install $(test "$YOUR_ENV" == production && echo "--no-dev")
这种方式$YOUR_ENV
将控制将安装哪个依赖项集:全部(默认)或仅带有--no-dev
标志的生产。
您可能还想添加一些其他选项以获得更好的体验:
--no-interaction
不要问任何互动问题--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
您可以在此处找到一个可以正常工作的真实示例:wemake-django-template
poetry
至1.0pip install poetry
是诗歌的依赖项可能与应用程序依赖项发生冲突。
poetry config virtualenvs.create false
在1.0.0中不起作用。使用RUN POETRY_VIRTUALENVS_CREATE=false poetry install
代替。
使用Poetry和venv的多阶段Docker构建
不要禁用virtualenv创建。Virtualenvs在Docker构建中有一个用途,因为它们提供了一种优雅的方式来利用多阶段构建。简而言之,您的构建阶段会将所有内容安装到virtualenv中,最后一步只是将virtualenv复制到一个小映像中。
poetry export
复制代码之前,请先使用并安装您的固定需求。这将允许您使用Docker构建缓存,而不必仅仅因为更改了代码行而重新安装了依赖项。
不要使用poetry install
安装代码,因为它将执行可编辑的安装。而是使用poetry build
构建轮子,然后将其通过pip安装到您的virtualenv中。(由于PEP 517,整个过程也可以用一个简单的方法执行pip install .
,但是由于构建隔离,您最终将安装另一本《 Poetry》。)
这是一个示例文件,该文件将Flask应用安装到Alpine映像中,并依赖于Postgres。本示例使用入口点脚本来激活virtualenv。但是通常,没有入口点脚本就可以了,因为您可以/venv/bin/python
在CMD
指令中简单地引用Python二进制文件。
Docker文件
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()
这是对我有用的最小配置:
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的configuration安全。
作为一个琐事,我要补充一点,如果可以对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
mymodule
您要安装的Python模块(如Poetry会在默认情况下找到一个模块),则需要在运行poetry install:之前创建一个虚拟版本,如下所示RUN mkdir /app/mymodule && touch /app/mymodule/__init__.py
。之所以可行,是因为Poetry使用pip -e安装了这些类型的模块,而pip -e只会创建一个符号链接。这意味着在最后一步中将实际模块复制到其上时,事情将按预期进行。(根据mods的说法,这是一种评价而不是编辑-如果您不同意,请尝试将其合并到帖子中。)
这是一个剥离的示例,其中首先将一个具有依赖项的层(仅在这些依赖项更改时才构建),然后将一个具有完整源代码的层添加到映像中。设置poetry
为安装到全局会site-packages
留下一个配置构件,也可以将其删除。
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 . ./
我已经能够建立poetry
一个Django
使用项目postgres
。经过研究后,我得出以下结论Dockerfile
:
FROM python:slim
# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE 1
# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED 1
# Install and setup poetry
RUN pip install -U pip \
&& apt-get update \
&& apt install -y curl netcat \
&& curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
ENV PATH="${PATH}:/root/.poetry/bin"
WORKDIR /usr/src/app
COPY . .
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
这是以下内容entrypoint.sh
:
#!/bin/sh
if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
fi
python manage.py migrate
exec "$@"
需要注意的几点:
我决定使用slim
而不是alpine
作为python
图像的标记,因为即使使用alpine
图像可以减小Docker图像的大小并加快构建速度,但使用Python最终可以得到更大的图像,并且要花一些时间才能完成。构建(有关更多信息,请阅读本文)。
使用此配置生成容器的速度比使用高山映像更快,因为我不需要添加一些额外的软件包即可正确安装Python软件包。
我poetry
直接从文档中提供的URL安装。我知道所提供的警告sobolevn
。但是,我认为从长远来看poetry
,默认情况下使用最新版本比依赖于我应定期更新的环境变量更好。
更新环境变量PATH
至关重要。否则,您将得到一条错误消息,指出未找到诗歌。
依赖关系直接安装在容器的python解释器中。它不会poetry
在安装依赖项之前创建虚拟环境。
如果您需要此alpine
版本Dockerfile
:
FROM python:alpine
# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE 1
# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED 1
# Install dev dependencies
RUN apk update \
&& apk add curl postgresql-dev gcc python3-dev musl-dev openssl-dev libffi-dev
# Install poetry
RUN pip install -U pip \
&& curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
ENV PATH="${PATH}:/root/.poetry/bin"
WORKDIR /usr/src/app
COPY . .
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
请注意,该alpine
版本需要一些依赖项postgresql-dev gcc python3-dev musl-dev openssl-dev libffi-dev
才能正常工作。
这是@Claudio提供的答案的次要修订,它使用了@sobolevn在其答案中poetry install --no-root
描述的新功能。
为了强制诗歌将依赖项安装到特定的virtualenv中,需要首先启用它。
. /path/to/virtualenv/bin/activate && poetry install
因此,将它们添加到@Claudio的答案中
FROM python:3.9-slim as base
ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1
RUN apt-get update && apt-get install -y gcc libffi-dev g++
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.1.3
RUN pip install "poetry==$POETRY_VERSION"
RUN python -m venv /venv
COPY pyproject.toml poetry.lock ./
RUN . /venv/bin/activate && poetry install --no-dev --no-root
COPY . .
RUN . /venv/bin/activate && poetry build
FROM base as final
COPY --from=builder /venv /venv
COPY --from=builder /app/dist .
COPY docker-entrypoint.sh ./
RUN . /venv/bin/activate && pip install *.whl
CMD ["./docker-entrypoint.sh"]
如果需要将其用于开发目的,请--no-dev
通过替换此行来添加或删除
RUN . /venv/bin/activate && poetry install --no-dev --no-root
如@sobolevn的答案所示
RUN . /venv/bin/activate && poetry install --no-root $(test "$YOUR_ENV" == production && echo "--no-dev")
添加适当的环境变量声明后。
该示例使用debian-slim作为基础,但是,使其适应于基于高山的图像应该是一件简单的任务。
poetry
最近才采用。)