0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

uv on Dockerでvenv仮想環境を作成しないPython開発用コンテナを構築する

Posted at

はじめに

私は現在Azure上で実行される生成AIアプリケーションの開発を行っていますが、 App Service・Functions へデプロイを行うにはコンテナを利用しないととてもじゃないがやってられないと感じています。

バックエンド側には生成AIや他ML等と相性が良いPythonを利用しているのですが、最近流行りのモジュール等管理ツール uv をコンテナで利用したい!動作速いし、依存関係も勝手に記載してくれる!・・・でも勝手に .venv が作成されるのが嫌だなと思った次第です。

image.png

そもそもが仮想環境であるDockerコンテナに venv 仮想環境をさらに作成する意味もありませんし、余計な管理コストや技術負債は増やしたくないものです。

作りたい環境のイメージ

  • pythonの開発用Dockerコンテナ
  • uv が高速かつ依存関係の自動記載等便利ため、開発・マルチステージBuilder用に使いたい
  • .venv を作りたくない
  • Docker内のシステムPythonのインストール先にモジュールをインストールしたい
  • 依存関係が記載されたファイル uv.lock はプロジェクト内のフォルダに配置しておきたい
  • 拡張機能などを自動でインストールしたいため、 Devcontainer 拡張機能を利用したい

結論

下記の環境変数をコンテナに設定する。

  • UV_SYSTEM_PYTHON=1
    • systemにインストールされているPythonを利用する
  • UV_PROJECT_ENVIRONMENT=/usr/local/
    • 使用するPython環境を /usr/local に設定し、 venv 環境を作成しない

事前準備

  • Docker開発環境( Docker Desktop Docker CLI 等)の構築
  • Visual Studio Code のインストール
  • Dev Containers 拡張機能のインストール

注意

  • 筆者の環境はWindows 11 24H2なのでmacやLinuxでは多少動作が異なるかもしれません
  • 本記事のDockerコンテナはRootで利用しているため、本場環境では作業用ユーザーの作成など行ってください
  • 本番用コンテナに uv がインストールされているべきではないため、本番環境の構築にはマルチステージビルドを利用してください

開発コンテナの構築

ディレクトリ構成

project-root>tree /F

project-root
  .python-version
  Dockerfile
  pyproject.toml
  README.md
  (ruff.toml)
  uv.lock
  
├─.devcontainer
      devcontainer.json
      
└─src
        hello.py

uv init 後の想定されるディレクトリ構成です。 ruff.tomlpyproject.toml と同一にして問題ありません。

Dockerfile

FROM python:3.11.9-slim-bookworm AS develop

WORKDIR /app

# uvの破壊的バージョンアップ対策として特定のバージョンを指定してインストール
COPY --from=ghcr.io/astral-sh/uv:0.5.3 /uv /uvx /bin/

ENV UV_SYSTEM_PYTHON=1 \
    UV_PROJECT_ENVIRONMENT=/usr/local/

RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
    --mount=type=cache,target=/var/cache/apt,sharing=locked \
    apt-get update

COPY . .

# 依存関係の解決(uv init後、uv.lock生成後にコメントアウト解除)
# RUN --mount=type=cache,target=/root/.cache,sharing=locked \
#     uv sync --frozen

今回ベースとなるコンテナイメージは、Debian bookworm slimpython 3.11.9 コンテナを利用しています。 Azure App ServiceAzure Functions のサポートするPythonバージョンが最近まで 3.11 までだった名残です。
uvはまだ登場したばかりで、ときたま破壊的なアップデートが行われるため、現状ですとバージョンを指定してインストールしておけばチームメンバー間での差異もなくなりよさそうです。
依存関係の解消部分は、 uv.lock ファイルが存在しないといけないため、 uv init を行った後にコメントアウトを解除してください。

Devcontainer.json

{
  "name": "My Dev Container",
  "workspaceFolder": "/app",
  "workspaceMount": "source=${localWorkspaceFolder},target=/app,type=bind,consistency=cached",
  "build": {
    "dockerfile": "../Dockerfile"
  },
  "settings": {},
  "extensions": [
    "ms-python.python",
    "ruffcharliermarsh.ruff"
  ]
}

ホストのカレントワークスペースフォルダをコンテナ内 /app にマウントしています。uv を使うなら同じくRustで作られたPythonのLinter・Formatter Ruff が便利です。

開発コンテナの起動

  1. Docker Desktop を起動します

  2. F1で Devcoitainers: Reopen in Container をクリックし、開発用コンテナを起動します

    image.png

  3. プロジェクトの初回起動時は、uvの初期設定コマンドを実行し、 pyproject.toml などを生成します

    user:/app# uv init
    
  4. プロジェクトで利用するpythonモジュールをインストールします

    user:/app# uv add requests
    Resolved 6 packages in 5ms
    Prepared 5 packages in 207ms
    Installed 5 packages in 7ms
     + certifi==2025.1.31
     + charset-normalizer==3.4.1
     + idna==3.10
     + requests==2.32.3
     + urllib3==2.3.0
    

1.uv.lockが生成されたら次回以降はDockerfileの uv sync 部分のコメントアウトを解除すれば、Dev ContainerでRebuildを行った際にも勝手に依存関係を解消してくれます。他メンバーがCloneして使う際もDockerfileで uv sync しておけば勝手に依存関係は解消されます。

各モジュールはシステムのPython user/local/site-package にインストールされており、 uv pip list でも、デフォルトの pip list でも同じ個所を参照してくれています。

user:/app# uv pip list
Using Python 3.11.9 environment at /usr/local
Package            Version
------------------ ---------
certifi            2025.1.31
charset-normalizer 3.4.1
idna               3.10
pip                24.0
requests           2.32.3
setuptools         65.5.1
urllib3            2.3.0
wheel              0.44.0
user:/app# pip list
Package            Version
------------------ ---------
certifi            2025.1.31
charset-normalizer 3.4.1
idna               3.10
pip                24.0
requests           2.32.3
setuptools         65.5.1
urllib3            2.3.0
wheel              0.44.0

プロジェクトのルートに .venv が作られず、Dockerコンテナ内のシステムPythonにパッケージがインストールされるようになりました!解決!

本番用コンテナを作成するときは、Composeのマルチステージビルドを利用して AS builderステージでuv sync --frozen --no-dev を行い site-packagesAS production にコピーすれば行けそうですね。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?