Can you give me an example of a Dockerfile
in which I can install all the packages I need from poetry.lock
and pyproject.toml
into my image/container from Docker?
There are several things to keep in mind when using poetry
together with docker
.
Official way to install poetry
is via:
curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
This way allows poetry
and its dependencies to be isolated from your dependencies. But, in my point of view, it is not a very good thing for two reasons:
poetry
version might get an update and it will break your build. In this case you can specify POETRY_VERSION
environment variable. Installer will respect itSo, I use pip install 'poetry==$POETRY_VERSION'
. As you can see, I still recommend to pin your version.
Also, pin this version in your pyproject.toml
as well:
[build-system]
# Should be the same as `$POETRY_VERSION`:
requires = ["poetry>=1.0"]
build-backend = "poetry.masonry.api"
It will protect you from version mismatch between your local and docker
environments.
We want to cache our requirements and only reinstall them when pyproject.toml
or poetry.lock
files change. Otherwise builds will be slow. To achieve working cache layer we should put:
COPY poetry.lock pyproject.toml /code/
After the poetry
is installed, but before any other files are added.
The next thing to keep in mind is virtualenv
creation. We do not need it in docker
. It is already isolated. So, we use poetry config virtualenvs.create false
setting to turn it off.
If you use the same Dockerfile
for both development and production as I do, you will need to install different sets of dependencies based on some environment variable:
poetry install $(test "$YOUR_ENV" == production && echo "--no-dev")
This way $YOUR_ENV
will control which dependencies set will be installed: all (default) or production only with --no-dev
flag.
You may also want to add some more options for better experience:
--no-interaction
not to ask any interactive questions--no-ansi
flag to make your output more log friendlyYou will end up with something similar to:
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
You can find a fully working real-life example here: wemake-django-template
poetry
to 1.0