Pouvez-vous s'il vous plaît me donner un exemple de Dockerfile dans lequel je peux installer tous les packages dont j'ai besoin de poetry.lock et pyproject.toml dans mon image/conteneur de Docker?
Il y a plusieurs choses à garder à l'esprit lorsque vous utilisez poetry
avec docker
.
La manière officielle d'installer poetry
est via:
curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
De cette façon, poetry
et ses dépendances peuvent être isolés de vos dépendances. Mais, à mon avis, ce n'est pas une très bonne chose pour deux raisons:
poetry
la version peut recevoir une mise à jour et elle cassera votre build. Dans ce cas, vous pouvez spécifier POETRY_VERSION
variable d'environnement. L'installateur le respecteraDonc, j'utilise pip install 'poetry==$POETRY_VERSION'
. Comme vous pouvez le voir, je recommande toujours d'épingler votre version.
Épinglez également cette version dans votre pyproject.toml
ainsi que:
[build-system]
# Should be the same as `$POETRY_VERSION`:
requires = ["poetry==0.12.11"]
build-backend = "poetry.masonry.api"
Il vous protègera de l'inadéquation des versions entre vos environnements local et docker
.
Nous voulons mettre en cache nos besoins et les réinstaller uniquement lorsque pyproject.toml
ou poetry.lock
les fichiers changent. Sinon, les builds seront lents. Pour obtenir une couche de cache fonctionnelle, nous devons mettre:
COPY poetry.lock pyproject.toml /code/
Après l'installation de poetry
, mais avant l'ajout de tout autre fichier.
La prochaine chose à garder à l'esprit est la création de virtualenv
. Nous n'en avons pas besoin dans docker
. Il est déjà isolé. Nous utilisons donc poetry config settings.virtualenvs.create false
réglage pour le désactiver.
Si vous utilisez le même Dockerfile
pour le développement et la production que moi, vous devrez installer différents ensembles de dépendances en fonction d'une variable d'environnement:
poetry install $(test "$YOUR_ENV" == production && echo "--no-dev")
Par ici $YOUR_ENV
contrôlera le jeu de dépendances qui sera installé: tout (par défaut) ou la production uniquement avec --no-dev
drapeau.
Vous pouvez également ajouter quelques options supplémentaires pour une meilleure expérience:
--no-interaction
ne pas poser de questions interactives--no-ansi
flag pour rendre votre sortie plus convivialeVous vous retrouverez avec quelque chose de similaire à:
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=0.12.11
# 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 settings.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
Vous pouvez trouver un exemple concret pleinement fonctionnel ici: wemake-Django-template
C'est une configuration minimale qui fonctionne pour moi:
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 settings.virtualenvs.create false
RUN poetry install --no-interaction
COPY . /app
Notez qu'il n'est pas aussi sûr que configuration de @ sobolevn .
Comme anecdote, j'ajouterai que si des installations modifiables seront possibles pour pyproject.toml
projets , une ou deux lignes pourraient être supprimées:
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
Construction Docker en plusieurs étapes avec poésie et venv
Ne désactivez pas la création de virtualenv. Virtualenvs sert un objectif dans les builds Docker , car ils fournissent un moyen élégant de tirer parti des builds à plusieurs étapes. En un mot, votre étape de construction installe tout dans le virtualenv, et la dernière étape copie simplement le virtualenv sur une petite image.
Si cela ne vous dérange pas d'utiliser la version préliminaire de Poetry, vous pouvez utiliser poetry export
et installez d'abord vos exigences épinglées avant de copier votre code. Cela vous permettra d'utiliser le cache de génération Docker et de ne jamais réinstaller les dépendances simplement parce que vous avez modifié une ligne dans votre code.
Ne pas utiliser poetry install
pour installer votre code, car il effectuera une installation modifiable. Utilisez plutôt poetry build
pour construire une roue, puis installez-la dans votre virtualenv. (Merci à PEP 517 , tout ce processus peut également être effectué avec un simple pip install .
, mais en raison de build isolation vous finiriez par installer une autre copie de Poetry.)
Voici un exemple Dockerfile installant une application Flask dans une image Alpine, avec une dépendance à Postgres. Cet exemple utilise un script de point d'entrée pour activer virtualenv. Mais en général, vous devriez être bien sans script de point d'entrée car vous pouvez simplement référencer le binaire Python à /venv/bin/python
dans votre instruction CMD
.
Dockerfile
FROM python:3.7.4-Alpine3.10 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.0b1
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()
Voici un exemple dépouillé où d'abord un calque avec les dépendances (qui n'est construit que lorsque celles-ci ont changé), puis un avec le code source complet est ajouté à une image. Configuration de poetry
pour une installation dans le global site-packages
laisse un artefact de configuration qui pourrait également être supprimé.
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 . ./