Интеграция Python Poetry с Docker

Можете ли вы привести пример Dockerfile, в котором я могу установить все необходимые пакеты из poetry.lock и pyproject.toml в свой образ / контейнер из Docker?


person Alex Bodea    schedule 18.12.2018    source источник


Ответы (8)


При использовании poetry вместе с docker следует помнить о нескольких вещах.

Установка

Официальный способ установки poetry:

curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -

Таким образом можно изолировать poetry и его зависимости от ваших зависимостей. Но, на мой взгляд, это не очень хорошо по двум причинам:

  1. Версия poetry может получить обновление, что нарушит вашу сборку. В этом случае вы можете указать POETRY_VERSION переменную среды. Установщик будет уважать это
  2. Мне не нравится идея передавать вещи из Интернета в мои контейнеры без какой-либо защиты от возможных изменений файлов.

Итак, я использую 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

Следующее, что нужно иметь в виду - это virtualenv творчество. В docker он нам не нужен. Он уже изолирован. Итак, мы используем настройку poetry config virtualenvs.create false, чтобы выключить его.

Разработка vs Производство

Если вы используете тот же Dockerfile как для разработки, так и для производства, что и я, вам нужно будет установить разные наборы зависимостей в зависимости от некоторой переменной среды:

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

Таким образом, $YOUR_ENV будет контролировать, какой набор зависимостей будет установлен: все (по умолчанию) или производственная версия только с флагом --no-dev.

Вы также можете добавить еще несколько опций для лучшего опыта:

  1. --no-interaction не задавать интерактивных вопросов
  2. --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

Обновление на 2019-12-17

  • Обновите poetry до 1.0
person sobolevn    schedule 19.02.2019
comment
Читатели этого ответа могут узнать о Многоступенчатые сборки Docker. Я знаю, что в моем случае многоступенчатые сборки значительно упростили процесс создания базовых и тестовых образов докеров приложений. См. также этот пост, который не посвящен стихам, но показывает причина, по которой можно рассмотреть возможность продолжения использования virtualenv в докере при выполнении многоэтапных сборок. (Еще не проверял, я только недавно принял poetry.) - person driftcatcher; 14.03.2019
comment
@hangtwenty заинтересованы ли вы в создании многоступенчатой ​​сборки для wemake-django-template? Это была бы отличная функция, которая уменьшит конечный размер изображения. Если да, напишите мне на github, создав новую проблему, пожалуйста. - person sobolevn; 14.03.2019
comment
Отличная идея! Открыл проблему. Я завален, но я найду время, чтобы внести свой вклад в ближайшее время - person driftcatcher; 15.03.2019
comment
@sobolevn единственное, что беспокоит pip install poetry, это то, что зависимости Poetry могут конфликтовать с зависимостями приложений. - person Rob Grant; 09.06.2019
comment
На самом деле поэзия поставляет пакеты, не предназначенные только для Python, что, к сожалению, делает их метод установки curl ненадежным. Я бы установил через pip, пока это не исправлено - person aaaaaa; 29.09.2019
comment
poetry config virtualenvs.create false не работает в 1.0.0. Вместо этого используйте RUN POETRY_VIRTUALENVS_CREATE=false poetry install. - person JerryDDG; 18.12.2019
comment
У меня все еще работает: travis-ci.com / wemake-services / wemake-django-template / jobs / Источник: github.com/wemake-services/wemake-django-template/blob/master/ - person sobolevn; 18.12.2019
comment
Чтобы легко копировать артефакты многоэтапной сборки с одного этапа на другой, я полагаюсь на --user arg на pip, так что я могу просто скопировать /root/.local на мой последний этап. Как бы я поступил так с поэзией? - person beeb; 04.06.2020
comment
Если вам нужно закрепить версию стихов в [build-system], не следует ли вам использовать poetry==1.0 вместо >=? - person ewen-lbh; 26.07.2020
comment
Фактически, установка поэзии с pip install действительно конфликтует с зависимостями приложения, поскольку у зависимостей поэзии также есть свои собственные зависимости. Это полностью под контролем разработчика. При использовании этого метода всегда рекомендуется использовать pip install --ignore-installed. Я тоже не люблю передавать что-то из Интернета прямо в оболочку. Не говоря уже о том, что для этого требуются curl, wget или что-то еще. Но, если вы решили это сделать, есть --version вариант get-poetry.py скрипта. - person tosh; 28.08.2020
comment
Этот метод оказался для меня само собой разумеющимся: в моем проекте pyproject.toml у меня все было настроено нормально. Однако pip install poetry (на Python 3.7) устанавливает appdirs как зависимость от poetry, как и предполагалось. Но при работе с config virtualenvs.create false, poetry запускается с нуля, а удаляет appdirs снова (Removing appdirs (1.4.4), при установке обычных зависимостей проекта все в порядке). Это потому, что appdirs не был указан в pyproject.toml (а зачем?). Я снова вернулся к использованию виртуальных окружений, так что poetry не удаляет appdirs. - person Alex Povel; 01.03.2021
comment
@AlexPovel, затем проверьте этот метод: github.com/wemake-services/wemake-django-template/blob/master/ - person sobolevn; 01.03.2021
comment
Как упоминалось в @AlexPovel, в настоящее время существует проблема, которая вызвана главным образом тем, что зависимости не разделены. Если вы используете dephell или black и у вас есть они в pyproject.toml в разделе dev-dependencies, материал взорвется, если вы установите с --no-dev. Одно из (надеюсь, временное) решение - установить поэзию официальным способом. - person Adrian Pop; 11.05.2021
comment
Это важно для КОПИРОВАНИЯ pyproject.toml вместе с poetry.lock? pyproject.toml также содержит, например, некоторую конфигурацию линтеров, и изменения в этом разделе вызывают ненужные промахи в кэше. Итак, можно ли КОПИРОВАТЬ только poetry.lock? - person dem1tris; 10.06.2021

Многоступенчатая сборка Docker с помощью Poetry и venv

Не отключайте создание virtualenv. Virtualenv служат определенной цели в сборках Docker, потому что они предоставляют элегантный способ использования многоэтапных сборок. Вкратце, на этапе сборки все устанавливается в virtualenv, а на последнем этапе просто копируется virtualenv в небольшой образ.

Используйте poetry export и сначала установите закрепленные требования, прежде чем копировать код. Это позволит вам использовать кеш сборки Docker и никогда не переустанавливать зависимости только потому, что вы изменили строку в своем коде.

Не используйте poetry install для установки вашего кода, потому что он выполнит установку, доступную для редактирования. Вместо этого используйте poetry build для создания колеса, а затем установите его в свой virtualenv. (Благодаря PEP 517 весь этот процесс можно также выполнить с помощью простого pip install ., но из-за изоляции сборки вам придется установить еще одну копию поэзии.)

Вот пример файла Dockerfile, устанавливающего приложение Flask в образ Alpine с зависимостью от Postgres. В этом примере используется сценарий точки входа для активации файла virtualenv. Но в целом у вас все будет хорошо без сценария точки входа, потому что вы можете просто сослаться на двоичный файл Python в /venv/bin/python в своей CMD инструкции.

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()
person Claudio    schedule 11.09.2019
comment
@stderr Редактируемая установка на самом деле не устанавливает ваш пакет в виртуальную среду. Он создает файл .egg-link, который ссылается на ваш исходный код, и эта ссылка будет действительна только на этапе сборки. - person Claudio; 08.12.2019
comment
Обновление: Выпущена Poetry 1.0.0. Предварительный выпуск больше не требуется для экспортных требований. - person Claudio; 13.12.2019
comment
Также ознакомьтесь с отличным руководством по упаковке Docker для Python от Itamar Turner-Trauring: pythonspeed.com/docker. Следуя его совету, этот ответ, вероятно, следует обновить, чтобы использовать тонкий образ Debian вместо Alpine. - person Claudio; 04.05.2020
comment
Не используйте поэтическую установку для установки вашего кода, потому что она выполнит установку с возможностью редактирования. Вы можете отключить это поведение с помощью флага --no-root. См. Закрытую проблему Github здесь. - person radzak; 05.05.2020
comment
Вы можете использовать poetry install --no-root вместо экспорта требований для pip install. Но это не помогает с редактируемыми установками. Эта проблема все еще не решена. - person Claudio; 05.05.2020
comment
Это все хорошо, за исключением случаев, когда poetry export -f requirements.txt генерирует недопустимые файлы требований: одни и те же записи дублируются. Похоже, это связано с попыткой поддержки разных версий Python. - person Matthew Schinckel; 04.06.2020
comment
Вместо использования virtualenv вы можете использовать установку пользователем (--user), а затем просто скопировать весь $HOME/.local/ в, e. грамм. /usr/bin/local/. Также есть параметры --root и --prefix pip, но кажется, что --root просто не работает (пункт 20.2), а --prefix расплывчато, и непонятно, что он на самом деле делает. И, как я уже сказал, нет причин использовать их, поскольку --user работает безупречно. - person tosh; 28.08.2020
comment
Кроме того, для меня идеальным случаем может быть предварительная обработка перед сборкой докеров, например. грамм. экспорт requirements.txt с использованием локально установленной поэзии. В таком случае мы могли бы даже отказаться от установки поэзии из нашего Dockerfile, что неплохо. К сожалению, это невозможно сделать с помощью самого докера. Определенно, это можно автоматизировать с помощью, например, грамм. сценарий оболочки, Makefile или что-то подобное. Однако мне такой подход кажется очень несовместимым со всем процессом сборки. - person tosh; 28.08.2020
comment
представил ревизию для замены шага генерации requirements.txt, и этот по-прежнему должен оставаться в нередактируемом состоянии - person Jeffrey04; 30.10.2020
comment
@ Jeffrey04 Не могли бы вы представить свою версию как отдельный ответ? В будущем я бы предпочел, чтобы вы сначала могли написать комментарий вместо того, чтобы продолжать и вносить существенные изменения в чей-то ответ. - person Claudio; 30.10.2020
comment
извините, не стесняйтесь вернуться к исходной версии - person Jeffrey04; 31.10.2020
comment
Обратите внимание, что у вас нет необходимости использовать venv для многоступенчатой ​​сборки. Вы также можете установить префикс для установки pip через переменную среды PIP_PREFIX. На базовом этапе отключите virtualenvs, установите префикс в новый каталог (например, /install, сначала mkdir!), И на последнем этапе скопируйте каталог префикса в префикс Python (может быть /usr, может быть /usr/local, может быть что-то еще). Предполагая, что официальные образы докеров Python и /install в качестве префикса, вы должны использовать COPY --from=base /install /usr/local. - person Martijn Pieters; 28.04.2021
comment
Вам не обязательно использовать . /venv/bin/activate, в Dockerfile достаточно использовать ENV PATH="/venv/bin:${PATH}" и ENV VIRTUAL_ENV="/venv", что означает, что у вас может быть встроенная точка входа / cmd, и он по-прежнему будет использовать venv. - person Duncan; 12.07.2021

Это минимальная конфигурация, которая мне подходит:

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
person maciek    schedule 22.02.2019
comment
Если ваш проект также содержит модуль Python mymodule, который вы хотели бы установить - как это делает Poetry по умолчанию, если он его находит, - вам нужно создать фиктивную версию, подобную этой, перед запуском поэзии install: RUN mkdir /app/mymodule && touch /app/mymodule/__init__.py. Это работает, потому что Poetry устанавливает эти типы модулей с помощью pip -e, который просто создает символическую ссылку. Это означает, что все работает должным образом, когда на последнем этапе поверх него копируются настоящие модули. (Согласно модам, это комментарий, а не редактирование - попробуйте включить его в сообщение, если вы не согласны.) - person Frankie Robertson; 23.04.2019

TL;DR

Мне удалось настроить 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 вы можете фактически получить изображение немного большего размера и это для сборки требуется время (дополнительную информацию см. в этой статье).

  • При использовании этой конфигурации контейнеры создаются быстрее, чем при использовании образа alpine, поскольку мне не нужно добавлять дополнительные пакеты для правильной установки пакетов 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.

person lmiguelvargasf    schedule 12.05.2020
comment
считают, что в долгосрочной перспективе лучше использовать позднюю версию поэзии - нет, действительно нет. Поскольку серьезное критическое изменение в каком-то новом выпуске Poetry может привести к поломке всей вашей сборки, вам все равно придется изменить ее, чтобы использовать жестко запрограммированную версию выпуска. - person OneCricketeer; 15.06.2021

Это незначительное изменение ответа, предоставленного @Claudio, в котором используется новая функция poetry install --no-root, описанная @sobolevn в своем ответе.

Чтобы заставить поэзию устанавливать зависимости в конкретный 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, однако адаптация его к образу на базе alpine должна быть тривиальной задачей.

person Jeffrey04    schedule 02.11.2020
comment
Мне очень нравится этот ответ, но как мне справиться с зависимостями локальных путей? - person DUWUDA; 03.02.2021
comment
что вы имеете в виду под зависимостями локальных путей? - person Jeffrey04; 03.02.2021
comment
Зависимости пути полезны в настройках монорепозитория, когда вы использовали общие библиотеки где-то еще в вашем репо, см. документы - person Luper Rouch; 04.02.2021
comment
добавить соответствующие команды COPY перед RUN poetry install или RUN poetry build, я полагаю? мой ответ (а также упомянутые) практически просто реплицирует настройку в контейнере, просто мы явно устанавливаем venv равным /venv/, если настройка в контейнере идентична вашей рабочей настройке, все технически должно работать нормально, просто подумайте как бы вы реплицировали настройку в другом месте без докера и соответствующим образом скорректировали Dockerfile? - person Jeffrey04; 05.02.2021

Вот пример, в котором сначала к изображению добавляется слой с зависимостями (который создается только при их изменении), а затем слой с полным исходным кодом. Установка 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 . ./
person funky-future    schedule 14.01.2019

Я создал решение, используя пакет блокировки (пакет, который зависит от всех версий в файле блокировки). Это приводит к чистой установке только pip без файлов требований.

Шаги: соберите пакет, соберите пакет блокировки, скопируйте оба колеса в свой контейнер, установите оба колеса с помощью pip.

Установка: poetry add --dev poetry-lock-package

Шаги за пределами сборки докера:

poetry build
poetry run poetry-lock-package --build

Тогда ваш Dockerfile должен содержать:

FROM python:3-slim

COPY dist/*.whl /

RUN pip install --no-cache-dir /*.whl \
    && rm -rf /*.whl

CMD ["python", "-m", "entry_module"]
person bneijt    schedule 30.04.2021
comment
идеальное решение. мой исходный комментарий об исходном коде python неверен, pip установит все в пакеты сайтов. - person kakarukeys; 22.06.2021

Я вижу, что все ответы здесь используют метод pip для установки Poetry, чтобы избежать проблем с версией. Официальный способ установки поэзии - чтение переменной env POETRY_VERSION, если она определена для установки наиболее подходящей версии.

здесь есть проблема в github, и я думаю, что решение из этого билета довольно интересно:

# `python-base` sets up all our shared environment variables
FROM python:3.8.1-slim as python-base

    # python
ENV PYTHONUNBUFFERED=1 \
    # prevents python creating .pyc files
    PYTHONDONTWRITEBYTECODE=1 \
    \
    # pip
    PIP_NO_CACHE_DIR=off \
    PIP_DISABLE_PIP_VERSION_CHECK=on \
    PIP_DEFAULT_TIMEOUT=100 \
    \
    # poetry
    # https://python-poetry.org/docs/configuration/#using-environment-variables
    POETRY_VERSION=1.0.3 \
    # make poetry install to this location
    POETRY_HOME="/opt/poetry" \
    # make poetry create the virtual environment in the project's root
    # it gets named `.venv`
    POETRY_VIRTUALENVS_IN_PROJECT=true \
    # do not ask any interactive question
    POETRY_NO_INTERACTION=1 \
    \
    # paths
    # this is where our requirements + virtual environment will live
    PYSETUP_PATH="/opt/pysetup" \
    VENV_PATH="/opt/pysetup/.venv"


# prepend poetry and venv to path
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"


# `builder-base` stage is used to build deps + create our virtual environment
FROM python-base as builder-base
RUN apt-get update \
    && apt-get install --no-install-recommends -y \
        # deps for installing poetry
        curl \
        # deps for building python deps
        build-essential

# install poetry - respects $POETRY_VERSION & $POETRY_HOME
RUN curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python

# copy project requirement files here to ensure they will be cached.
WORKDIR $PYSETUP_PATH
COPY poetry.lock pyproject.toml ./

# install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally
RUN poetry install --no-dev


# `development` image is used during development / testing
FROM python-base as development
ENV FASTAPI_ENV=development
WORKDIR $PYSETUP_PATH

# copy in our built poetry + venv
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH

# quicker install as runtime deps are already installed
RUN poetry install

# will become mountpoint of our code
WORKDIR /app

EXPOSE 8000
CMD ["uvicorn", "--reload", "main:app"]


# `production` image used for runtime
FROM python-base as production
ENV FASTAPI_ENV=production
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
COPY ./app /app/
WORKDIR /app
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "main:app"]
person Mattia Fantoni    schedule 18.04.2021
comment
На самом деле вам не нужен venv при запуске кода в контейнере - person OneCricketeer; 15.06.2021