Integrating Python Poetry with Docker

后端 未结 7 430
轻奢々
轻奢々 2021-01-29 17:51

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 imag

相关标签:
7条回答
  • 2021-01-29 18:35

    There are several things to keep in mind when using poetry together with docker.

    Installation

    Official way to install poetry is via:

    curl -sSL https://raw.githubusercontent.com/python-poetry/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:

    1. 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 it
    2. I do not like the idea to pipe things from the internet into my containers without any protection from possible file modifications

    So, 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.

    Caching dependencies

    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.

    Virtualenv

    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.

    Development vs Production

    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:

    1. --no-interaction not to ask any interactive questions
    2. --no-ansi flag to make your output more log friendly

    Result

    You 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

    Update on 2019-12-17

    • Update poetry to 1.0
    0 讨论(0)
提交回复
热议问题