Integration von Python Poetry in Docker

Lesezeit: 14 Minuten

Benutzeravatar von Alex Bodea
Alex Bodea

Können Sie mir ein Beispiel geben für a Dockerfile in der ich alle Pakete installieren kann, die ich benötige poetry.lock und pyproject.toml in mein Image/Container von Docker?

Benutzeravatar von sobolevn
sobolewn

Bei der Verwendung gibt es einiges zu beachten poetry zusammen mit docker.

Installation

Offizielle Art der Installation poetry ist über:

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

Dieser Weg ermöglicht poetry und seine Abhängigkeiten von Ihren Abhängigkeiten isoliert werden. Aber aus meiner Sicht ist es aus zwei Gründen keine sehr gute Sache:

  1. poetry Version erhält möglicherweise ein Update und es wird Ihren Build beschädigen. In diesem Fall können Sie angeben POETRY_VERSION Umgebungsvariable. Der Installer wird es respektieren
  2. Ich mag die Idee nicht, Dinge aus dem Internet ohne jeglichen Schutz vor möglichen Dateiänderungen in meine Container zu leiten

Also benutze ich pip install 'poetry==$POETRY_VERSION'. Wie Sie sehen können, empfehle ich dennoch, Ihre Version zu pinnen.

Pinnen Sie diese Version auch in Ihrer pyproject.toml auch:

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

Es schützt Sie vor Versionskonflikten zwischen Ihrem lokalen und docker Umgebungen.

Caching-Abhängigkeiten

Wir möchten unsere Anforderungen zwischenspeichern und nur dann neu installieren, wenn pyproject.toml oder poetry.lock Dateien ändern sich. Andernfalls werden Builds langsam sein. Um eine funktionierende Cache-Schicht zu erreichen, sollten wir Folgendes eingeben:

COPY poetry.lock pyproject.toml /code/

Nach dem poetry installiert ist, aber bevor andere Dateien hinzugefügt werden.

Virtualenv

Das nächste, was Sie beachten sollten, ist virtualenv Schaffung. Wir brauchen es nicht drin docker. Es ist bereits isoliert. Also verwenden wir poetry config virtualenvs.create false Einstellung, um es auszuschalten.

Entwicklung vs. Produktion

Wenn Sie das gleiche verwenden Dockerfile Sowohl für die Entwicklung als auch für die Produktion müssen Sie, wie ich es tue, verschiedene Sätze von Abhängigkeiten basierend auf einer Umgebungsvariable installieren:

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

Diesen Weg $YOUR_ENV steuert, welche Abhängigkeiten installiert werden: alle (Standard) oder nur Produktion mit --no-dev Flagge.

Möglicherweise möchten Sie auch einige weitere Optionen für eine bessere Erfahrung hinzufügen:

  1. --no-interaction keine interaktiven Fragen zu stellen
  2. --no-ansi -Flag, um Ihre Ausgabe log-freundlicher zu machen

Ergebnis

Am Ende erhalten Sie etwas Ähnliches wie:

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

Ein voll funktionsfähiges Beispiel aus der Praxis finden Sie hier: wemake-django-template

Aktualisierung am 17.12.2019

  • Aktualisieren poetry auf 1,0

  • Leser dieser Antwort können Informieren Sie sich über mehrstufige Docker-Builds. Ich weiß, dass in meinem Fall mehrstufige Builds den Prozess von Basis- vs. Test- vs. App-Docker-Images erheblich vereinfacht haben. Siehe auch diesen Beitrag die nicht poesiespezifisch ist, aber einen Grund dafür zeigt könnte Erwägen Sie, virtualenv weiterhin innerhalb von Docker zu verwenden, wenn Sie mehrstufige Builds durchführen. (Selbst noch nicht getestet, habe ich nur angenommen poetry in letzter Zeit.)

    – m_floer

    14. März 2019 um 0:54 Uhr

  • @sobolevn die einzige Sorge mit pip install poetry besteht darin, dass die Abhängigkeiten von Poetry mit App-Abhängigkeiten in Konflikt geraten können.

    – Rob Grant

    9. Juni 2019 um 13:21 Uhr

  • poetry config virtualenvs.create false funktioniert nicht in 1.0.0. Verwenden RUN POETRY_VIRTUALENVS_CREATE=false poetry install stattdessen.

    – JerryDDG

    18. Dezember 2019 um 3:14 Uhr

  • Eigentlich Installation Poesie mit pip install tun Konflikt mit App-Abhängigkeiten, da Poesie-Abhängigkeiten auch ihre eigenen Abhängigkeiten haben. Es ist absolut unter der Kontrolle des Entwicklers. Mit dieser Methode wird immer empfohlen, sie zu verwenden pip install --ignore-installed. Ich mag es auch nicht, etwas aus dem Internet direkt in die Shell zu leiten. Ganz zu schweigen davon, dass es curl, wget oder irgendetwas anderes erfordert. Aber wenn Sie sich dafür entschieden haben, gibt es sie --version Option von get-poetry.py Skript.

    – Antonius

    28. August 2020 um 14:13 Uhr

  • Diese Methode fiel für mich ins eigene Gesicht: in meinem Projekt pyproject.toml, ich hatte alles normal eingerichtet. Jedoch, pip install poetry (auf Python 3.7) installiert appdirs als Abhängigkeit von poetry, wie beabsichtigt. Aber beim Laufen mit config virtualenvs.create false, poetry läuft “Bare-Metal” und entfernt appdirs wieder (Removing appdirs (1.4.4), während die Installation normaler Projektabhängigkeiten in Ordnung ist). Das ist weil appdirs wurde nicht aufgeführt pyproject.toml (weil warum sollte es?). Ich habe wieder virtuelle Envs verwendet, damit poetry entfernt nicht appdirs.

    – Alex Powel

    1. März 2021 um 11:30 Uhr

Claudios Benutzeravatar
Claudio

Mehrstufiger Docker-Build mit Poetry und venv

Deaktivieren Sie die Erstellung von virtualenv nicht. Virtualenvs erfüllen einen Zweck in Docker-Builds, da sie eine elegante Möglichkeit bieten, mehrstufige Builds zu nutzen. Kurz gesagt, Ihre Build-Phase installiert alles in der virtuellen Umgebung, und die letzte Phase kopiert die virtuelle Umgebung einfach in ein kleines Image.

Verwenden poetry export und installieren Sie zuerst Ihre angehefteten Anforderungen, bevor Sie Ihren Code kopieren. Auf diese Weise können Sie den Docker-Build-Cache verwenden und niemals Abhängigkeiten neu installieren, nur weil Sie eine Zeile in Ihrem Code geändert haben.

Verwende nicht poetry install um Ihren Code zu installieren, da er eine bearbeitbare Installation durchführt. Verwenden Sie stattdessen poetry build um ein Rad zu bauen, und installieren Sie es dann per Pip in Ihrer virtuellen Umgebung. (Dank an PEP 517könnte dieser ganze Vorgang auch mit einem einfachen durchgeführt werden pip install .aber wegen Isolation aufbauen Sie würden am Ende eine weitere Kopie von Poetry installieren.)

Hier ist ein Dockerfile-Beispiel, das eine Flask-App in einem Alpine-Image installiert, mit einer Abhängigkeit von Postgres. In diesem Beispiel wird ein Einstiegspunktskript verwendet, um die virtualenv zu aktivieren. Aber im Allgemeinen sollten Sie ohne ein Einstiegspunktskript auskommen, da Sie einfach auf die Python-Binärdatei unter verweisen können /venv/bin/python in deiner CMD Anweisung.

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()

  • Update: Poetry 1.0.0 wurde veröffentlicht. Zum Exportieren von Anforderungen ist keine Vorabversion mehr erforderlich.

    – Claudio

    13. Dezember 2019 um 16:19 Uhr

  • Sehen Sie sich auch Itamar Turner-Traurings ausgezeichneten Docker-Paketierungsleitfaden für Python an: pythonspeed.com/docker. Nach seinem Rat sollte diese Antwort wahrscheinlich aktualisiert werden, um ein schlankes Debian-Image anstelle von Alpine zu verwenden.

    – Claudio

    4. Mai 2020 um 14:19 Uhr

  • “Verwenden Sie keine Poesie-Installation, um Ihren Code zu installieren, da dies eine bearbeitbare Installation durchführt.” Sie können dieses Verhalten mit deaktivieren --no-root Flagge. Sehen Sie sich ein geschlossenes Github-Problem an hier.

    – Radzak

    5. Mai 2020 um 14:36 ​​Uhr

  • Das ist alles schön und gut, außer es gibt Zeiten, wo poetry export -f requirements.txt generiert ungültige Anforderungsdateien: dieselben Einträge werden dupliziert. Dies scheint mit dem Versuch zusammenzuhängen, verschiedene Versionen von Python zu unterstützen.

    – Matthäus Schinckel

    4. Juni 2020 um 7:30 Uhr

  • Sie müssen nicht verwenden . /venv/bin/activatees reicht im Dockerfile zu verwenden ENV PATH="/venv/bin:${PATH}" und ENV VIRTUAL_ENV="/venv" was bedeutet, dass Sie einen Inline-Einstiegspunkt/cmd haben können und dieser weiterhin die venv.

    – Duncan

    12. Juli 2021 um 16:47 Uhr

Benutzeravatar von lmiguelvargasf
lmiguelvargasf

TL;DR

konnte ich einrichten poetry Für ein Django Projekt verwenden postgres. Nach einigen Recherchen bin ich zu folgendem Ergebnis gekommen 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"]

Dies ist der Inhalt von 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 "$@"

Ausführliche Erklärung

Einige Punkte zu beachten:

  • Ich habe mich für die Verwendung entschieden slim Anstatt von alpine als Tag für die python Bild, weil obwohl alpine Images sollen die Größe von Docker-Images reduzieren und den Build beschleunigen, mit Python können Sie tatsächlich mit einem etwas größeren Image enden und das zu bauen dauert eine Weile (lesen Sie Dieser Artikel Für mehr Information).

  • Mit dieser Konfiguration werden Container schneller erstellt als mit dem Alpine-Image, da ich keine zusätzlichen Pakete hinzufügen muss, um Python-Pakete ordnungsgemäß zu installieren.

  • Ich installiere poetry direkt von der in der Dokumentation angegebenen URL. Die Warnhinweise von sind mir bekannt sobolevn. Langfristig halte ich es jedoch für besser, die neueste Version von zu verwenden poetry standardmäßig, anstatt mich auf eine Umgebungsvariable zu verlassen, die ich regelmäßig aktualisieren sollte.

  • Aktualisieren der Umgebungsvariable PATH ist entscheidend. Andernfalls erhalten Sie eine Fehlermeldung, die dies besagt Gedichte wurden nicht gefunden.

  • Abhängigkeiten werden direkt im Python-Interpreter des Containers installiert. Es schafft nicht poetry um eine virtuelle Umgebung zu erstellen, bevor Sie die Abhängigkeiten installieren.

Falls Sie die benötigen alpine Version davon 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"]

Beachten Sie, dass die alpine Version benötigt einige Abhängigkeiten postgresql-dev gcc python3-dev musl-dev openssl-dev libffi-dev richtig zu arbeiten.

  • bedenken Sie, dass es langfristig besser ist, die späteste Version der Poesie zu verwenden – Nein, wirklich nicht. Da eine wichtige Breaking Change in einer neuen Version von Poetry Ihren gesamten Build beschädigen kann, müssten Sie ihn so ändern, dass er sowieso eine fest codierte Release-Version verwendet

    – OneCricketeer

    15. Juni 2021 um 6:16 Uhr


  • ich benutze curl -sSL https://install.python-poetry.org | python - --version 1.1.13 um eine Version anzugeben und den Build nicht zu beschädigen

    – Kriza

    7. April um 16:28 Uhr

  • Wie kann ich das mit a zum Laufen bringen nicht gerooted Benutzer im Docker? Ich erhalte poetry not found wenn es als Nicht-Root-Benutzer versucht wird.

    – brennt0907

    24. August um 21:32 Uhr


Dies ist eine geringfügige Überarbeitung der Antwort von @Claudio, die das Neue verwendet poetry install --no-root Funktion, wie von @sobolevn in seiner Antwort beschrieben.

Um zu zwingen Poesie Um Abhängigkeiten in einer bestimmten virtuellen Umgebung zu installieren, muss man sie zuerst aktivieren.

. /path/to/virtualenv/bin/activate && poetry install

Daher fügen wir diese in die Antwort von @Claudio ein, die wir haben

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"]

Wenn Sie dies für Entwicklungszwecke verwenden müssen, fügen Sie die hinzu oder entfernen Sie die --no-dev indem Sie diese Zeile ersetzen

RUN . /venv/bin/activate && poetry install --no-dev --no-root

zu so etwas wie in der Antwort von @sobolevn gezeigt

RUN . /venv/bin/activate && poetry install --no-root $(test "$YOUR_ENV" == production && echo "--no-dev")

nach dem Hinzufügen der entsprechenden Deklaration der Umgebungsvariablen.

Das Beispiel verwendet debian-slim als Basis, die Anpassung an ein Alpine-basiertes Image sollte jedoch eine triviale Aufgabe sein.

Benutzeravatar von maciek
maciek

Das ist die minimale Konfiguration, die für mich funktioniert:

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

Beachten Sie, dass dies nicht so sicher ist wie die Konfiguration von @sobolevn.

Als Trivia füge ich das hinzu wenn bearbeitbare Installationen möglich sind pyproject.toml Projekteein oder zwei Zeilen könnten gelöscht werden:

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

  • Gegebenenfalls enthält Ihr Projekt auch ein Python-Modul mymodule dass Sie installiert werden möchten — wie es Poetry standardmäßig tut, wenn es eine findet — müssen Sie eine Dummy-Version wie diese erstellen, bevor Sie die Poesie-Installation ausführen: RUN mkdir /app/mymodule && touch /app/mymodule/__init__.py. Das funktioniert, weil Poetry diese Art von Modulen mit pip -e installiert, was nur einen symbolischen Link erstellt. Das bedeutet, dass das Ding wie erwartet funktioniert, wenn im letzten Schritt die echten Module darüber kopiert werden. (Laut Mods ist dies ein Kommentar und keine Bearbeitung – bitte versuchen Sie, ihn in den Beitrag zu integrieren, wenn Sie nicht einverstanden sind.)

    – Frankie Robertson

    23. April 2019 um 10:37 Uhr


Benutzeravatar von funky-future
Funky-Zukunft

Hier ist ein abgespecktes Beispiel, bei dem zuerst ein Layer mit den Abhängigkeiten (der nur erstellt wird, wenn sich diese geändert haben) und dann einer mit dem vollständigen Quellcode zu einem Image hinzugefügt wird. Einstellung poetry in die globale zu installieren site-packages hinterlässt ein Konfigurationsartefakt, das ebenfalls entfernt werden könnte.

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 . ./

  • Gegebenenfalls enthält Ihr Projekt auch ein Python-Modul mymodule dass Sie installiert werden möchten — wie es Poetry standardmäßig tut, wenn es eine findet — müssen Sie eine Dummy-Version wie diese erstellen, bevor Sie die Poesie-Installation ausführen: RUN mkdir /app/mymodule && touch /app/mymodule/__init__.py. Das funktioniert, weil Poetry diese Art von Modulen mit pip -e installiert, was nur einen symbolischen Link erstellt. Das bedeutet, dass das Ding wie erwartet funktioniert, wenn im letzten Schritt die echten Module darüber kopiert werden. (Laut Mods ist dies ein Kommentar und keine Bearbeitung – bitte versuchen Sie, ihn in den Beitrag zu integrieren, wenn Sie nicht einverstanden sind.)

    – Frankie Robertson

    23. April 2019 um 10:37 Uhr


Mein Dockerfile basierend auf der Antwort von @lmiguelvargasf. Beziehen Sie sich auf seinen Beitrag für eine detailliertere Erklärung. Die einzigen wesentlichen Änderungen, die ich habe, sind die folgenden:

  • Ich verwende jetzt den neuesten offiziellen Installer install-poetry.py statt der veralteten get-poetry.py wie in ihrer offiziellen Dokumentation empfohlen. Ich installiere auch eine bestimmte Version mit dem --version Flag, aber Sie können alternativ die Umgebungsvariable verwenden POETRY_VERSION. Weitere Informationen zu ihren offiziellen Dokumenten!

  • Das PATH Ich benutze ist /root/.local/bin:$PATH Anstatt von ${PATH}:/root/.poetry/bin aus OPs 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()" ]

  • Ihr [main page]((python-poetry.org/docs)) empfiehlt immer noch die Github-URL, die alle anderen erwähnt haben. Die Verwendung des hier erwähnten Installationsprogramms liest sich nicht POETRY_VIRTUALENVS_CREATE Umgebungsvariable, nicht sicher, ob es einen Fehler mit ENVs hat oder nicht.

    – anishtain4

    14. April um 20:40 Uhr

  • “Der PATH, den ich verwende, ist /root/.local/bin:$PATH” <-- Das ist großartig, aber... Könnten Sie bitte einen Grund erklären? Vielen Dank.

    – Nairum

    14. Juni um 12:11 Uhr

  • Das ist kein mehrstufiger Build und Sie müssen die Abhängigkeiten jedes Mal installieren, wenn Sie den Container erstellen.

    – Ivailo Bardarov

    29. Juni um 7:38 Uhr

  • Bonuspunkte für poetry run gunicorn 🙂

    – rjurney

    27. Juli um 22:54 Uhr

  • positiv bewertet! warum diese Zeile? Poetry Config virtualenvs.create false Was passiert, wenn Dockerr eine .venv-Datei in Ihrem Projekt erstellt?

    – PirateApp

    1. August um 11:13 Uhr

1398290cookie-checkIntegration von Python Poetry in Docker

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy