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?
Integration von Python Poetry in Docker
Alex Bodea
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:
poetry
Version erhält möglicherweise ein Update und es wird Ihren Build beschädigen. In diesem Fall können Sie angebenPOETRY_VERSION
Umgebungsvariable. Der Installer wird es respektieren- 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:
--no-interaction
keine interaktiven Fragen zu stellen--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. VerwendenRUN 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 verwendenpip 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 vonget-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) installiertappdirs
als Abhängigkeit vonpoetry
, wie beabsichtigt. Aber beim Laufen mitconfig virtualenvs.create false
,poetry
läuft “Bare-Metal” und entferntappdirs
wieder (Removing appdirs (1.4.4)
, während die Installation normaler Projektabhängigkeiten in Ordnung ist). Das ist weilappdirs
wurde nicht aufgeführtpyproject.toml
(weil warum sollte es?). Ich habe wieder virtuelle Envs verwendet, damitpoetry
entfernt nichtappdirs
.– Alex Powel
1. März 2021 um 11:30 Uhr
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
-
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/activate
es reicht im Dockerfile zu verwendenENV PATH="/venv/bin:${PATH}"
undENV 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
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 vonalpine
als Tag für diepython
Bild, weil obwohlalpine
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 bekanntsobolevn
. Langfristig halte ich es jedoch für besser, die neueste Version von zu verwendenpoetry
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.
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
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 veraltetenget-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 verwendenPOETRY_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
Es gibt einen wirklich guten Diskussionsthread auf GitHub. Hier ist ein Link zu meiner Methode: github.com/python-poetry/poetry/discussions/…
– Kann H. Tartanoglu
8. Mai um 16:19 Uhr