はじめに
絵羽模様😭😭😭 nikkieです。
先日の、uvでライブラリとして環境構築したPythonプロジェクトのDockerイメージの記事を更新します。
コメントいただき、uvだけで達成できました。
ありがとうございます!
目次
- はじめに
- 目次
- uv init --libで環境構築して開発中の自作Pythonライブラリを含んだDockerイメージをビルドする
- コメントでuv buildを教わる
- 改訂版の結論
- wheelをビルドしてインストールすることで、editableでないインストールを達成する
- 終わりに
uv init --libで環境構築して開発中の自作Pythonライブラリを含んだDockerイメージをビルドする
プロジェクト構造
mylib/ ├── .venv/ ├── .python-version ├── src/ │ └── mylib/ │ ├── __init__.py │ ├── __main__.py │ └── py.typed ├── pyproject.toml └── uv.lock
% uv run python -m mylib Hello from mylib! ['kokoro', 'aki', 'fuka', 'rion', 'subaru', 'masamune', 'ureshino']
python -m mylibを実行するDockerイメージを作りました。
https://gist.github.com/ftnext/5b0bb4784d806140aea22a807f171fef
- マルチステージビルド
- 前段のuvのDockerイメージで、仮想環境(
.venv)に全ての依存をインストール。これを成果物イメージにコピーするだけ - 成果物イメージはpythonイメージ。uvは含めない
- 前段のuvのDockerイメージで、仮想環境(
- uvはプロジェクト自体をeditable installするので、仮想環境にライブラリ自体のコードがコピーされない課題があった
- 仮想環境にpipを入れ(ensurepip)、
pip installしてライブラリ自体のコードをコピーした(ねじ伏せた💪)
- 仮想環境にpipを入れ(ensurepip)、
uvでライブラリ自体のeditableでないインストールもできればいいのですが、editable installのみのように思われたので、pipを持ち出しています。
コメントでuv buildを教わる
今のuvなら `uv build` でwheelが生成できるので、
— kAZUYA tAKEI (@attakei) 2024年9月15日
RUN uv build
RUN --mount=bind=(略) pip install
の組み合わせのほうがサイズはちょっと小さくなるっぽいです。
※依存ライブラリのインストール速度が遅くかも
※同じ出力なのは確認ずみhttps://t.co/1GOZK5qpqX
uvはプロジェクトをビルドできます(uv build)。
ビルドしてできたwheelからインストールすれば、editableでないインストール(=ソースコードをコピーするインストール)になると気づきました!
おおー、なるほど!
— nikkie / にっきー 技書博 け-04 Python型ヒント本 (@ftnext) 2024年9月15日
uv buildを使うというのは見えていませんでした。
こちらの方が行数も短く収まってよさそうです👏
ありがとうごさいます!
私の方でも確認して記事を更新します
改訂版の結論
% docker run --rm uv-practice-lib:0.2.0 Hello from mylib! ['kokoro', 'aki', 'fuka', 'rion', 'subaru', 'masamune', 'ureshino']
全容はこちらからどうぞ
wheelをビルドしてインストールすることで、editableでないインストールを達成する
差分箇所について、置き換えたコマンドを見ていきます
RUN <<INSTALL_PROJECT - .venv/bin/python -m ensurepip - .venv/bin/python -m pip install --no-deps . + uv build + uv pip install --no-deps dist/mylib-*.whl INSTALL_PROJECT
uv build
「Working on projects」のドキュメントより
https://docs.astral.sh/uv/guides/projects/#building-distributions
uv buildcan be used to build source distributions and binary distributions (wheel) for your project.
uv buildを叩くとdistディレクトリができて、そこに配布物(distribution)が2つの形式でできます
% uv build Building source distribution... Building wheel from source distribution... Successfully built dist/mylib-0.1.0.tar.gz and dist/mylib-0.1.0-py3-none-any.whl
- source distribution (sdist)
- ref: ソースコード配布物 (またはsdist)
- binary distribution
さらに詳しいドキュメントはこちら
https://docs.astral.sh/uv/concepts/projects/#building-projects
--sdistや--wheelというフラグを指定して、sdistやwheelの欲しい方だけを作ることもできるようです。
uv pip install
https://docs.astral.sh/uv/reference/cli/#uv-pip-install
uv buildしたwheelですが、(pip installでできるように)uv pip installでもwheelからインストールできます。
その際、--no-depsは指定し続けています
Ignore package dependencies, instead only installing those packages explicitly listed on the command line or in the requirements files
Dockerfileの uv sync --frozen --no-dev --no-install-project の行で、プロジェクト(今回は自作ライブラリ)が依存するライブラリをすべてインストールしています。
--frozenの指定により、uv.lockの記載と同じバージョンの依存がインストールされます。
残るインストールは、自作ライブラリ本体です。
自作ライブラリのwheelをインストールするときに--no-depsを指定して、自作ライブラリだけを、ソースコードをコピーしてインストールしています
終わりに
uvで環境構築したPythonライブラリのDockerイメージについて、いただいたコメントをもとに改訂しました。
- マルチステージビルドで成果物イメージからuvは除く
- ライブラリ自体のeditableでないインストールのために、uvでwheelをビルドし、それをインストールした
- 開発中のライブラリを含むすべての依存ライブラリをステージ間でコピーした
uv buildしてwheelからインストールすればeditableでないインストールができるというのは、見えていませんでした。
attakeiさん、コメント誠にありがとうございます!
nikkie、uv、なかよし、なかよし