記事
2026年10月22日

PyPIミラー実践ガイド Pythonパッケージを安定してインストールするために

PyPIミラー実践ガイド Pythonパッケージを安定してインストールするために

何か月も問題なく動いていたPythonのビルドが、新しい環境では失敗する。アプリケーションコードを変更していなくても、固定していたバージョンのパッケージがPyPIから削除されたり、固定していない依存パッケージに別のバージョンが選ばれたりすることで、こうした問題は起こります。

PyPIミラーは対策の一つですが、何を保存する仕組みなのかによって、解決できる問題が異なります。配布元と同期するミラー、要求されたファイルを保存するキャッシュ、過去のインデックスを保持するミラーは、それぞれ役割が違います。

この記事では、その違いと、pip・uv・Poetryでの設定方法を説明します。ロックファイルと併用する際の考え方や、自社で運用する場合の確認事項も取り上げます。

PyPIミラーとは

PyPIミラーとは、Python Package Index(PyPI)で配布されるパッケージを、別の取得先から利用できるようにする仕組みです。繰り返し発生するダウンロードの削減、オフライン環境での利用、公開パッケージへのアクセス管理などに使われます。

Pythonのインストールツールは、互換性のあるパッケージインデックスを、公開PyPIの代わりに参照できます。pipの場合は、--index-urlで参照先を指定します。

pip install \
  --index-url https://mirror.example.com/simple/ \
  requests

ただし、この設定だけでは、接続先が全パッケージを同期しているのか、要求されたファイルだけをキャッシュしているのか、過去の状態まで保持しているのかは分かりません。用途に合うかを判断するには、保存と更新の仕組みを確認する必要があります。

全体を同期するミラーは、配布元のインデックスとパッケージファイルをコピーします。必要なファイルがすべてそろっていれば、オフラインでのインストールにも利用できます。

PyPIキャッシュミラーは、クライアントが要求したファイルを取得し、後のリクエストに再利用します。古いファイルを引き続き取得できるかどうかは、保存と更新の方針によって決まります。

履歴型のミラーは、過去のインデックスを保持し、指定した時点の情報で依存関係を解決します。ただし、インデックスの履歴とパッケージファイルの保持は別の要素です。履歴の対象期間と、対応するファイルの保持範囲を合わせて確認してください。

一つのパッケージを固定しても依存関係全体は固定されない

直接利用するパッケージのバージョンを指定しても、そのパッケージが依存するすべてのバージョンまで固定されるとは限りません。

onnx==1.14.0

例えば、このリリースが依存するprotobufには、厳密なバージョン指定ではなく、下限を定めた条件が設定されています。依存関係全体を固定していなければ、後日同じ指定でインストールしても、条件に合う別のバージョンが選ばれる可能性があります。

ロックファイルは、解決済みの依存関係を記録することで、この問題に対処します。ただし、パッケージファイルそのものを保存するわけではありません。記録したファイルが配布元から削除されれば、バージョンを正確に指定していてもダウンロードできなくなります。

StableBuildが公開する「Deleted PyPI Package Index」では、PyPIから削除されたパッケージやバージョンを確認できます。バージョンを指定することと、そのファイルを継続して取得できることが、別の問題であると分かる具体例です。

また、新しい依存関係を追加したり、ロックファイルを再生成したりすると、依存関係の解決が再び必要になります。その際に参照する現在のインデックスには、プロジェクトの開始時には存在しなかったバージョンが含まれていることがあります。

StableBuildがPyPIの履歴を保持する仕組み

StableBuildはPyPIインデックスのスナップショットを毎日保存し、パッケージファイルは要求された時点でキャッシュします。また、PyPIでファイルやバージョンの削除を検知した際にも、取得可能なファイルをキャッシュします。日付を含むURLを指定すると、依存関係の解決に使うインデックスの時点を選べます。

pip install \
  -i https://your-domain.pypimirror.stablebuild.com/2026-10-01/ \
  -r requirements.txt

your-domainは、アカウントに割り当てられたミラードメインに置き換えてください。この例では、2026年10月1日時点のインデックスを参照します。それより後にアップロードされたパッケージは、依存関係の解決候補に入りません。

日付を固定したインデックスだけで、同一の環境が保証されるわけではありません。Pythonのバージョン、OSやCPUアーキテクチャ、インストールツールなど、ほかのビルド条件も管理する必要があります。

日付を固定せず、現在のインデックスを参照しながらファイルをキャッシュしたい場合は、liveを指定します。

pip install \
  -i https://your-domain.pypimirror.stablebuild.com/live/ \
  requests

完全な日次インデックスの保存は、2023年9月21日から行われています。それ以前の日付は、保持している情報から再構成されるため、当時の状態と異なる場合があります。保存前に削除されたパッケージなどは、取得できないことがあります。

出典:StableBuild PyPIミラーのドキュメント

pipでミラーを設定する

pipでは、--index-urlまたは短縮形の-iを使って、パッケージの取得先を指定します。個別のパッケージにも、requirements.txtにも利用できます。CIでは、毎回のコマンドにURLを書く代わりに、pipの設定ファイルや環境変数PIP_INDEX_URLで管理する方法もあります。

ここで行っているのは、既存のミラーへの接続設定です。インストールツールの参照先を変更しても、ミラーサーバー自体が構築されるわけではありません。アカウント固有のURLにAPIキーが含まれている場合は、URL全体を認証情報として扱い、公開リポジトリやログに残さないよう管理してください。

uvでPyPIミラーを使う

uvでPyPIミラーを使う場合は、pyproject.tomlにインデックスを定義します。

[[tool.uv.index]]
name = "stablebuild"
url = "https://your-domain.pypimirror.stablebuild.com/2026-10-01/"
default = true

default = trueを指定すると、uvが標準で参照する公開PyPIを、このインデックスに置き換えられます。ただし、ほかにもインデックスを設定している場合、それらが優先されることがあります。プロジェクト全体の設定を確認してください。

uvは標準設定では、対象のパッケージが最初に見つかったインデックスに候補バージョンを限定します。公開パッケージと社内パッケージの取得先を併用する場合は、uvのインデックス選択ルールを確認したうえで設定します。

PoetryでPyPIミラーを使う

Poetryは、Simple Repository APIに対応したリポジトリを利用できます。pyproject.tomlに、次の設定を追加します。

[[tool.poetry.source]]
name = "stablebuild"
url = "https://your-domain.pypimirror.stablebuild.com/2026-10-01/"
priority = "primary"

primaryの取得先を設定すると、Poetryが標準で参照する公開PyPIは無効になります。別のprimaryソースも設定されていれば、Poetryはそれらも検索します。公開PyPIを明示的に追加することも可能です。社内パッケージの取得先と併用する場合は、ソースの優先順位と、パッケージごとの取得先指定を確認してください。

Poetryのソース設定はパッケージの標準メタデータには含まれません。そのプロジェクトを別の利用者がpipでインストールしても、Poetryの設定が自動的に引き継がれるわけではありません。詳しくは、Poetryのリポジトリ設定を参照してください。

自社でPyPIミラーを構築し運用する

外部ネットワークから切り離された環境でパッケージを利用したい場合や、配布基盤を自社で直接管理する必要がある場合は、プライベートPyPIミラーの運用も選択肢になります。ここでは、公開PyPIのパッケージを社内向けに提供するミラーを指します。自社製パッケージを公開するリポジトリとは、役割を分けて考える必要があります。

PyPIミラーの構築方法の一つが、PyPAのミラークライアントであるbandersnatchの利用です。bandersnatchでPyPIミラーを構築すると、パッケージのメタデータや配布ファイルを同期できます。フィルターを使い、保存するパッケージやファイルを絞ることも可能です。

PyPIミラーの容量は、保存対象によって大きく変わります。全体をコピーする場合は、対象を限定したミラーや、チームが利用するファイルだけを保存するキャッシュよりも、多くのストレージが必要になります。容量は増え続けるため、過去の固定値ではなく、PyPIが公開する統計を確認して見積もるのが適切です。

運用では、同期処理、通信量、監視、バックアップ、可用性も管理します。オフラインで利用する場合は、ネットワークを切り離す前に、必要な配布ファイルがすべてそろっているか確認してください。未取得のファイルを、キャッシュから提供することはできません。

社内パッケージの公開、アクセス制御、成果物の管理まで必要であれば、ArtifactoryやNexusなどのリポジトリ管理製品も検討対象になります。その際は、キャッシュ機能があるだけで過去のファイルが無期限に保持されると考えず、製品と設定ごとの保存方針を確認します。

参考:bandersnatch公式ドキュメント

ロックファイルと更新管理を組み合わせる

PyPIミラーは、バージョン制約、ロックファイル、ハッシュ検証を補完します。これらのツールが参照するインデックスと、取得できるパッケージファイルを管理するものであり、依存関係の確認やセキュリティ更新を不要にするものではありません。

必要なのがオフラインでの利用なら、必要なファイルをそろえた同期型ミラーが候補になります。重複ダウンロードの削減が目的なら、キャッシュが役立ちます。過去のプロジェクトを当時利用可能だったパッケージで解決したい場合は、履歴型のインデックスが検討対象になります。

StableBuildを利用する場合は、PyPIミラーの設定ガイドに沿って、日付指定またはliveのエンドポイントを設定してください。CIに組み込む前に、キャッシュのない新しい環境でビルドし、意図した依存関係が選ばれることを確認します。