Können Sie mir ein Beispiel geben, Dockerfile
in dem ich alle benötigten Pakete von poetry.lock
und pyproject.toml
in mein Image / Container von Docker installieren kann ?
Können Sie mir ein Beispiel geben, Dockerfile
in dem ich alle benötigten Pakete von poetry.lock
und pyproject.toml
in mein Image / Container von Docker installieren kann ?
Antworten:
Bei der Verwendung poetry
mit sind verschiedene Dinge zu beachten docker
.
Die offizielle Installation poetry
erfolgt über:
curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
Auf diese Weise können poetry
und ihre Abhängigkeiten von Ihren Abhängigkeiten isoliert werden. Aber aus meiner Sicht ist es aus zwei Gründen keine sehr gute Sache:
poetry
Die Version wird möglicherweise aktualisiert und Ihr Build wird beschädigt. In diesem Fall können Sie eine POETRY_VERSION
Umgebungsvariable angeben . Der Installer wird es respektierenAlso benutze ich pip install 'poetry==$POETRY_VERSION'
. Wie Sie sehen können, empfehle ich weiterhin, Ihre Version zu pinnen.
Stecken Sie diese Version auch in Ihre pyproject.toml
:
[build-system]
# Should be the same as `$POETRY_VERSION`:
requires = ["poetry>=1.0"]
build-backend = "poetry.masonry.api"
Es schützt Sie vor Versionsinkongruenzen zwischen Ihrem lokalen und dem docker
Umfeld.
Wir wollen , dass unsere Anforderungen zwischenzuspeichern und sie nur neu installieren , wenn pyproject.toml
oder poetry.lock
Dateien ändern. Andernfalls werden die Builds langsam sein. Um eine funktionierende Cache-Schicht zu erreichen, sollten wir Folgendes setzen:
COPY poetry.lock pyproject.toml /code/
Nach der poetry
Installation, aber bevor andere Dateien hinzugefügt werden.
Das nächste, was zu beachten ist, ist die virtualenv
Schöpfung. Wir brauchen es nicht in docker
. Es ist bereits isoliert. Also verwenden wir die poetry config virtualenvs.create false
Einstellung, um es auszuschalten.
Wenn Sie Dockerfile
für Entwicklung und Produktion dasselbe verwenden wie ich, müssen Sie verschiedene Abhängigkeiten basierend auf einer Umgebungsvariablen installieren:
poetry install $(test "$YOUR_ENV" == production && echo "--no-dev")
Auf diese Weise $YOUR_ENV
wird gesteuert, welche Abhängigkeiten festgelegt werden: alle (Standard) oder Produktion nur mit --no-dev
Flag.
Möglicherweise möchten Sie auch weitere Optionen hinzufügen, um eine bessere Erfahrung zu erzielen:
--no-interaction
keine interaktiven Fragen zu stellen--no-ansi
Flag, um Ihre Ausgabe protokollfreundlicher zu gestaltenSie werden am Ende etwas Ähnliches haben 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
poetry
auf 1.0pip install poetry
ist, dass die Abhängigkeiten von Poetry mit App-Abhängigkeiten in Konflikt stehen könnten.
poetry config virtualenvs.create false
funktioniert nicht in 1.0.0. Verwenden Sie RUN POETRY_VIRTUALENVS_CREATE=false poetry install
stattdessen.
Mehrstufiger Docker Build mit Poetry und Venv
Deaktivieren Sie die Erstellung von virtualenv nicht. Virtualenvs erfüllen in Docker-Builds einen Zweck , da sie eine elegante Möglichkeit bieten, mehrstufige Builds zu nutzen. Kurz gesagt, Ihre Build-Phase installiert alles in die virtuelle 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 Abhängigkeiten niemals neu installieren, nur weil Sie eine Zeile in Ihrem Code geändert haben.
Verwenden poetry install
Sie diesen Code nicht zur Installation, da er eine bearbeitbare Installation ausführt. Verwenden Sie stattdessen, poetry build
um ein Rad zu bauen, und installieren Sie es dann per Pip in Ihre virtuelle Umgebung. (Dank PEP 517 könnte dieser gesamte Prozess auch mit einem einfachen Vorgang ausgeführt werden. pip install .
Aufgrund der Build-Isolation würden Sie jedoch eine weitere Kopie von Poetry installieren.)
Hier ist ein Beispiel für eine Docker-Datei, in der eine Flask-App in einem Alpine-Image installiert wird, abhängig von Postgres. In diesem Beispiel wird ein Einstiegspunktskript verwendet, um die virtuelle Umgebung zu aktivieren. Im Allgemeinen sollten Sie jedoch ohne ein Einstiegspunktskript in Ordnung sein, da Sie /venv/bin/python
in Ihrer CMD
Anweisung einfach auf die Python-Binärdatei verweisen können .
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()
Das ist eine 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 es nicht so sicher ist wie die Konfiguration von @ sobolevn .
Als Trivia möchte ich hinzufügen, dass ein oder zwei Zeilen gelöscht werden könnten , wenn bearbeitbare Installationen für pyproject.toml
Projekte möglich sind :
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
, das Sie installieren möchten - wie es Poetry standardmäßig tut, wenn es eines findet - müssen Sie eine Dummy-Version wie diese erstellen, bevor Sie die Poetry-Installation ausführen : RUN mkdir /app/mymodule && touch /app/mymodule/__init__.py
. Dies funktioniert, weil Poetry diese Art von Modulen mit pip -e installiert, wodurch nur eine symbolische Verknüpfung erstellt wird. Dies bedeutet, dass die Dinge wie erwartet funktionieren, wenn die realen Module im letzten Schritt darüber kopiert werden. (Laut Mods ist dies ein Kommentar und keine Bearbeitung - bitte versuchen Sie es in den Beitrag aufzunehmen, wenn Sie nicht einverstanden sind.)
Hier ist ein Beispiel, bei dem zuerst eine Ebene mit den Abhängigkeiten (die nur erstellt wird, wenn sich diese ändern) und dann eine Ebene mit dem vollständigen Quellcode zu einem Bild hinzugefügt wird. Bei der Einstellung poetry
für die Installation in der globalen Datei site-packages
bleibt ein Konfigurationsartefakt erhalten, das ebenfalls entfernt werden kann.
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 . ./
Ich konnte mich mit poetry
für ein Django
Projekt einrichten postgres
. Nach einigen Recherchen kam ich zu folgendem Ergebnis 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 "$@"
Einige Punkte zu beachten:
Ich habe mich entschieden, slim
anstelle von alpine
als Tag für das python
Bild zu verwenden, denn obwohl alpine
Bilder die Größe von Docker-Bildern reduzieren und den Build beschleunigen sollen, können Sie mit Python tatsächlich ein etwas größeres Bild erhalten, und das dauert eine Weile Build (lesen Sie diesen Artikel für weitere Informationen).
Mit dieser Konfiguration werden Container schneller erstellt als mit dem alpinen 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. Mir sind die Warnungen von bekannt sobolevn
. Ich bin jedoch der Meinung, dass es auf lange Sicht besser ist, die spätere Version poetry
von standardmäßig zu verwenden, als sich auf eine Umgebungsvariable zu verlassen, die ich regelmäßig aktualisieren sollte.
Das Aktualisieren der Umgebungsvariablen PATH
ist von entscheidender Bedeutung. Andernfalls erhalten Sie eine Fehlermeldung, dass keine Poesie gefunden wurde .
Abhängigkeiten werden direkt im Python-Interpreter des Containers installiert. Es wird keine poetry
virtuelle Umgebung erstellt, bevor die Abhängigkeiten installiert werden.
Falls Sie die alpine
Version davon benötigen 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 einige Abhängigkeiten benötigt postgresql-dev gcc python3-dev musl-dev openssl-dev libffi-dev
, um ordnungsgemäß zu funktionieren.
Dies ist eine geringfügige Überarbeitung der Antwort von @Claudio , die die neue poetry install --no-root
Funktion verwendet, wie sie von @sobolevn in seiner Antwort beschrieben wurde .
Um Poesie zu zwingen , Abhängigkeiten in eine bestimmte virtuelle Umgebung zu installieren, muss sie zuerst aktiviert werden.
. /path/to/virtualenv/bin/activate && poetry install
Fügen Sie diese daher zu @ Claudios Antwort hinzu, 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 das hinzu oder entfernen Sie es, --no-dev
indem Sie diese Zeile ersetzen
RUN . /venv/bin/activate && poetry install --no-dev --no-root
zu so etwas wie in @ sobolevns Antwort gezeigt
RUN . /venv/bin/activate && poetry install --no-root $(test "$YOUR_ENV" == production && echo "--no-dev")
nach dem Hinzufügen der entsprechenden Umgebungsvariablendeklaration.
In diesem Beispiel werden Debian-Slims als Basis verwendet. Die Anpassung an ein alpines Bild sollte jedoch eine triviale Aufgabe sein.
poetry
kurzem adoptiert .)