例えば以下のような開発用のDockerfileがあったとする。
FROM python:3.12 ENV UV_PROJECT_ENVIRONMENT="/usr/local/" WORKDIR /app ADD pyproject.toml ./ ADD uv.lock ./ RUN pip install uv RUN uv sync --frozen --no-cache
その場合開発時はリアルタイムにファイル内容を更新したいので、ホストのカレントディレクトリと/appをマウントしてコンテナを起動したい。
そうするとDockerfileでビルドした.venvが消えてしまう。
uvはデフォルトでは、プロジェクトごとに隔離された環境、すなわち仮想環境(.venv
)を生成する。
これは、Pythonの依存関係をプロジェクトごとに分離し、異なるプロジェクト間でのパッケージの競合を避けるためだ。
uv sync
コマンドは、この分離された環境に依存パッケージをインストールする。これにより、システムのPython環境を汚染することなく、プロジェクト固有の依存関係を管理できる。
調べると UV_SYSTEM_PYTHON=true
をつけると.venvを作らずにシステムのパッケージとしてインストールされるらしい。
ENV UV_SYSTEM_PYTHON=true
しかし
だが、試してみても依然として.venvはつくられたままだった。調べると uv sync
には効かないらしい。
対策
結果的には UV_PROJECT_ENVIRONMENT="/usr/local/"
を付与することでシステムのパッケージとしてインストールできた。
FROM python:3.12 ENV UV_PROJECT_ENVIRONMENT="/usr/local/" WORKDIR /app ADD pyproject.toml ./ ADD uv.lock ./ RUN pip install uv RUN uv sync --frozen --no-cache
UV_PROJECT_ENVIRONMENT
は、uvが依存パッケージをインストールするベースディレクトリを定義する環境変数だ。
デフォルトでは、プロジェクトディレクトリ内に .venv
ディレクトリが作成され、そこにパッケージがインストールされる。
しかし、この環境変数を /usr/local/
に設定すると、uvはシステムのパッケージディレクトリ(/usr/local/lib/python3.x/site-packages/
)に直接パッケージをインストールするようになる。
これは、実質的に仮想環境を使わずに、システム全体にパッケージをインストールすることと同じだ。
/usr/local/
を指定する理由は、このディレクトリが一般的にシステム管理者がパッケージをインストールする場所として使用され、システムの他のPython環境と競合しにくいためだ。
Docker環境においては、このディレクトリは通常コンテナイメージのレイヤーの一部となり、コンテナ内の全てのプロセスで共有されることになる。