コンテンツにスキップ

pex でマルチステージビルドを行う

Pants で Python アプリケーションを pex にまとめるとき、ソースと外部パッケージを別々に構築して Docker のキャッシュを使いやすくします。BUILDファイルと Dockerfile の例を使い、マルチステージビルドの構成を説明します。

マルチステージビルドとは

マルチステージビルドとは、Dockerfile のビルドステージを複数に分けるビルド手法です。ビルドに必要なファイルと実行に必要なファイルを分離できます。ファイル分離により、最終的なイメージサイズを小さくしたり、キャッシュを効きやすくしたりできます。

pex でマルチステージビルドを行う

pex は、Python の依存パッケージを含めた実行可能な単一ファイルを作成するツールです。 この例では、ソースコードと外部パッケージを分けて pex を構築し、Dockerfile の別々のステージで処理します。依存パッケージが変わらなければ、その部分のキャッシュを再利用できるため、ビルド時間の短縮が期待できます。

例

Pants を使った次のようなディレクトリ構成を想定します。

1
2
3
4
5
.
├── Dockerfile
├── requirements.txt
├── BUILD
└── main.py

次のように pex を構築すると、ソースと 3rd party パッケージを分離できます。

BUILD
pex_binary(
    name="binary-deps",
    execution_mode="venv",
    entry_point="main.py",
    layout="packed",
    include_sources=False,
    include_tools=True,
)

pex_binary(
    name="binary-srcs",
    execution_mode="venv",
    entry_point="main.py",
    layout="packed",
    include_requirements=False,
    include_tools=True,
)
BUILD
docker_image(
    name="img-deps",
    registries=["foo"],
    repository="deps",
    image_tags=[
        "latest",
    ],
    instructions=[
        "FROM python:3.11-slim",
        "COPY binary-deps.pex /binary-deps.pex",
        "RUN PEX_TOOLS=1 python3.11 /binary-deps.pex venv --scope=deps --compile /bin/app",
    ],
)

docker_image(
    source=None,
    name="img-srcs",
    registries=["foo"],
    repository="srcs",
    image_tags=[
        "latest",
    ],
    instructions=[
        "FROM python:3.11-slim",
        "COPY binary-srcs.pex /binary-srcs.pex",
        "RUN PEX_TOOLS=1 python3.11 /binary-srcs.pex venv --scope=srcs --compile /bin/app",
    ],
)

docker_image(
    source="Dockerfile",
    name="final-image",
    registries=["foo"],
    repository="bar",
    image_tags=["latest"],
    dependencies=[
        ":img-srcs",
        ":img-deps",
    ],
)
Dockerfile
1
2
3
4
FROM python:3.11-slim
COPY --from=foo/deps:latest /bin/app /bin/app
COPY --from=foo/srcs:latest /bin/app /bin/app
ENTRYPOINT ["/bin/app/pex"]

上記のコードを使ってコンテナイメージをビルドします。キャッシュが効きやすくなり、ビルド時間の短縮も期待できます。

注意点

ビルド時と実行時で、Python のパスが違うと動かない場合があります。パスが異なる場合は、pex 構築のオプションでshebangを指定するか、シンボリックリンクを張るなどの対応が必要です。