web-dev-qa-db-ja.com

Python PoetryとDockerの統合

Poetry.lockとpyproject.tomlから必要なすべてのパッケージをDockerから自分のイメージ/コンテナーにインストールできるDockerfileの例を教えてください。

9
Alex Bodea

poetrydockerと一緒に使用する場合、留意すべき点がいくつかあります。

Installation

poetryをインストールする公式の方法は次のとおりです:

curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python

この方法により、poetryとその依存関係を依存関係から分離できます。しかし、私の観点では、次の2つの理由からあまり良いことではありません。

  1. poetryバージョンは更新を取得する可能性があり、ビルドが中断します。この場合、POETRY_VERSION環境変数を指定できます。インストーラーはそれを尊重します
  2. ファイルの変更の可能性から保護せずに、インターネットからコンテナにパイプするという考えが好きではありません

そこで、pip install 'poetry==$POETRY_VERSION'を使用します。ご覧のとおり、バージョンを固定することをお勧めします。

また、pyproject.tomlにもこのバージョンを固定します:

[build-system]
# Should be the same as `$POETRY_VERSION`:
requires = ["poetry==0.12.11"]
build-backend = "poetry.masonry.api"

ローカル環境とdocker環境間のバージョンの不一致から保護します。

依存関係のキャッシュ

要件をキャッシュし、pyproject.tomlまたはpoetry.lockファイルが変更された場合にのみ再インストールします。そうしないと、ビルドが遅くなります。作業キャッシュレイヤーを実現するには、以下を配置する必要があります。

COPY poetry.lock pyproject.toml /code/

poetryがインストールされた後、他のファイルが追加される前。

Virtualenv

次に留意することは、virtualenvの作成です。 dockerでは必要ありません。すでに分離されています。したがって、poetry config settings.virtualenvs.create false設定を使用してオフにします。

開発vs生産

私と同じDockerfileを開発と本番の両方に使用する場合、いくつかの環境変数に基づいて異なる依存関係のセットをインストールする必要があります。

poetry install $(test "$YOUR_ENV" == production && echo "--no-dev")

このように、$YOUR_ENVは、どの依存関係セットをインストールするかを制御します:all(デフォルト)または--no-devフラグを使用した実動のみ。

より良い体験のために、いくつかのオプションを追加することもできます。

  1. --no-interactionインタラクティブな質問をしない
  2. --no-ansiフラグを使用すると、出力のログがよりわかりやすくなります

結果

次のような結果になります。

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

完全に動作する実際の例をここで見つけることができます: wemake-Django-template

33
sobolevn

それは私のために働く最小限の構成です:

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

@ sobolevnの設定 ほど安全ではないことに注意してください。

トリビアとして、それを追加します 編集可能なインストールがpyproject.tomlプロジェクト 、1行または2行を削除できます。

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
5
maciek

Poetryとvenvを使用したマルチステージDockerビルド

Virtualenvの作成を無効にしないでください。 VirtualenvはDockerビルドで目的を果たします 。これは、マルチステージビルドを活用するエレガントな方法を提供するためです。簡単に言うと、ビルドステージはすべてをvirtualenvにインストールし、最後のステージではvirtualenvを小さなイメージにコピーします。

Poetryプレリリースの使用を気にしない場合は、コードをコピーする前に、poetry exportを使用し、固定された要件を最初にインストールできます。これにより、Dockerビルドキャッシュを使用でき、コードの行を変更しただけで依存関係を再インストールすることはできません。

poetry installを使用してコードをインストールしないでください。編集可能なインストールが実行されるためです。代わりに、poetry buildを使用してホイールを構築し、それをvirtualenvにpipインストールします。 ( PEP 517 のおかげで、このプロセス全体は単純なpip install .でも実行できますが、 build isolation により、詩の別のコピーをインストールすることになります)

以下は、Postgresに依存する、AlpineイメージにFlaskアプリをインストールするDockerfileの例です。この例では、エントリーポイントスクリプトを使用してvirtualenvをアクティブにします。 CMD命令の/venv/bin/pythonでPythonバイナリを参照するだけでよいためです。

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()
2
Claudio

以下は、最初に依存関係を持つレイヤー(これらが変更されたときにのみビルドされる)と、次に完全なソースコードを持つレイヤーがイメージに追加されるストリップされた例です。 poetryを設定してグローバルにインストールするsite-packagesは、削除できる構成アーティファクトを残します。

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 . ./
1
funky-future