Skip to content

Dockerでuvを使用する

はじめに

Tip

Dockerでアプリケーションをビルドする際のベストプラクティスの例として、uv-docker-exampleプロジェクトを参照してください。

コンテナ内でuvを実行する

ビルド済みのuvが利用可能なDockerイメージが公開されています。コンテナ内でuvコマンドを実行するには:

$ docker run ghcr.io/astral-sh/uv --help

利用可能なイメージ

uvはuvバイナリを含むdistroless Dockerイメージを提供しています。以下のタグが公開されています:

  • ghcr.io/astral-sh/uv:latest
  • ghcr.io/astral-sh/uv:{major}.{minor}.{patch}, e.g., ghcr.io/astral-sh/uv:0.5.1
  • ghcr.io/astral-sh/uv:{major}.{minor}, e.g., ghcr.io/astral-sh/uv:0.5 (the latest patch version)

さらに、uvは以下のイメージも公開しています:

  • alpine:3.20ベース:
    • ghcr.io/astral-sh/uv:alpine
    • ghcr.io/astral-sh/uv:alpine3.20
  • debian:bookworm-slimベース:
    • ghcr.io/astral-sh/uv:debian-slim
    • ghcr.io/astral-sh/uv:bookworm-slim
  • buildpack-deps:bookwormベース:
    • ghcr.io/astral-sh/uv:debian
    • ghcr.io/astral-sh/uv:bookworm
  • python3.x-alpineベース:
    • ghcr.io/astral-sh/uv:python3.13-alpine
    • ghcr.io/astral-sh/uv:python3.12-alpine
    • ghcr.io/astral-sh/uv:python3.11-alpine
    • ghcr.io/astral-sh/uv:python3.10-alpine
    • ghcr.io/astral-sh/uv:python3.9-alpine
    • ghcr.io/astral-sh/uv:python3.8-alpine
  • python3.x-bookwormベース:
    • ghcr.io/astral-sh/uv:python3.13-bookworm
    • ghcr.io/astral-sh/uv:python3.12-bookworm
    • ghcr.io/astral-sh/uv:python3.11-bookworm
    • ghcr.io/astral-sh/uv:python3.10-bookworm
    • ghcr.io/astral-sh/uv:python3.9-bookworm
    • ghcr.io/astral-sh/uv:python3.8-bookworm
  • python3.x-slim-bookwormベース:
    • ghcr.io/astral-sh/uv:python3.13-bookworm-slim
    • ghcr.io/astral-sh/uv:python3.12-bookworm-slim
    • ghcr.io/astral-sh/uv:python3.11-bookworm-slim
    • ghcr.io/astral-sh/uv:python3.10-bookworm-slim
    • ghcr.io/astral-sh/uv:python3.9-bookworm-slim
    • ghcr.io/astral-sh/uv:python3.8-bookworm-slim

As with the distroless image, each image is published with uv version tags as ghcr.io/astral-sh/uv:{major}.{minor}.{patch}-{base} and ghcr.io/astral-sh/uv:{major}.{minor}-{base}, e.g., ghcr.io/astral-sh/uv:0.5.1-alpine.

詳細については、GitHub Containerページを参照してください。

uvのインストール

uvが事前にインストールされた上記のイメージのいずれかを使用するか、公式のdistroless Dockerイメージからバイナリをコピーしてuvをインストールします:

Dockerfile
FROM python:3.12-slim-bookworm
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

または、インストーラーを使用します:

Dockerfile
FROM python:3.12-slim-bookworm

# インストーラーはリリースアーカイブをダウンロードするためにcurl(および証明書)を必要とします
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates

# 最新のインストーラーをダウンロード
ADD https://astral.sh/uv/install.sh /uv-installer.sh

# インストーラーを実行して削除
RUN sh /uv-installer.sh && rm /uv-installer.sh

# インストールされたバイナリが `PATH` にあることを確認
ENV PATH="/root/.local/bin/:$PATH"

この方法ではcurlが利用可能である必要があります。

いずれの場合も、特定のuvバージョンに固定することがベストプラクティスです。例:

COPY --from=ghcr.io/astral-sh/uv:0.5.1 /uv /uvx /bin/

または、インストーラーを使用する場合:

ADD https://astral.sh/uv/0.5.1/install.sh /uv-installer.sh

プロジェクトのインストール

uvを使用してプロジェクトを管理している場合、イメージにコピーしてインストールできます:

Dockerfile
# プロジェクトをイメージにコピー
ADD . /app

# 凍結されたロックファイルを使用して新しい環境にプロジェクトを同期
WORKDIR /app
RUN uv sync --frozen

Important

プロジェクトの仮想環境はローカルプラットフォームに依存しており、イメージ内で新たに作成する必要があるため、リポジトリ内の.dockerignoreファイル.venvを追加することがベストプラクティスです。

次に、デフォルトでアプリケーションを起動するには:

Dockerfile
# プロジェクトが提供する`my_app`コマンドを前提としています
CMD ["uv", "run", "my_app"]

Tip

Dockerイメージのビルド時間を改善するために、依存関係のインストールとプロジェクト自体のインストールを分離する中間レイヤーを使用することがベストプラクティスです。

完全な例はuv-docker-exampleプロジェクトで確認できます。

環境の使用

プロジェクトがインストールされたら、仮想環境のバイナリディレクトリをパスの先頭に配置してプロジェクト仮想環境を_アクティブ化_することができます:

Dockerfile
ENV PATH="/app/.venv/bin:$PATH"

または、環境を必要とするコマンドにはuv runを使用できます:

Dockerfile
RUN uv run some_script.py

Tip

代わりに、プロジェクト環境パスの設定を行うUV_PROJECT_ENVIRONMENT設定を同期前に設定して、システムPython環境にインストールし、環境のアクティブ化をスキップすることもできます。

インストールされたツールの使用

インストールされたツールを使用するには、ツールバインディレクトリがパスに含まれていることを確認します:

Dockerfile
ENV PATH=/root/.local/bin:$PATH
RUN uv tool install cowsay
$ docker run -it $(docker build -q .) /bin/bash -c "cowsay -t hello"
  _____
| hello |
  =====
     \
      \
        ^__^
        (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

Note

ツールバインディレクトリの場所は、コンテナ内でuv tool dir --binコマンドを実行して確認できます。

代わりに、一定の場所に設定することもできます:

Dockerfile
ENV UV_TOOL_BIN_DIR=/opt/uv-bin/

muslベースのイメージでのPythonのインストール

uvは互換性のあるPythonバージョンをインストールしますが、muslベースのディストリビューション用のPythonのインストールはまだサポートしていません。例えば、PythonがインストールされていないAlpine Linuxベースのイメージを使用している場合、システムパッケージマネージャーで追加する必要があります:

apk add --no-cache python3~=3.12

コンテナでの開発

開発時には、プロジェクトディレクトリをコンテナにマウントすることが有用です。このセットアップでは、プロジェクトへの変更がイメージを再ビルドすることなくコンテナ化されたサービスに即座に反映されます。ただし、プロジェクト仮想環境(.venv)をマウントに含めないことが重要です。仮想環境はプラットフォーム固有であり、イメージ用にビルドされたものを保持する必要があります。

docker runでプロジェクトをマウントする

作業ディレクトリ内のプロジェクトを/appにバインドマウントし、匿名ボリュームで.venvディレクトリを保持します:

$ docker run --rm --volume .:/app --volume /app/.venv [...]

Tip

コンテナが終了したときにコンテナと匿名ボリュームがクリーンアップされるように、--rmフラグを含めています。

完全な例はuv-docker-exampleプロジェクトで確認できます。

docker composeでのwatchの設定

Docker composeを使用する場合、コンテナ開発のためのより高度なツールが利用可能です。 watchオプションは、バインドマウントよりも細かい粒度での設定が可能であり、ファイルが変更されたときにコンテナ化されたサービスの更新をトリガーすることができます。

Note

この機能は、Docker Desktop 4.24にバンドルされているCompose 2.22.0が必要です。

プロジェクトディレクトリを仮想環境を同期せずにマウントし、構成が変更されたときにイメージを再ビルドするようにwatchを設定します:

compose.yaml
services:
  example:
    build: .

    # ...

    develop:
      # アプリを更新するための`watch`設定を作成
      #
      watch:
        # 作業ディレクトリをコンテナ内の`/app`ディレクトリと同期
        - action: sync
          path: .
          target: /app
          # プロジェクト仮想環境を除外
          ignore:
            - .venv/

        # `pyproject.toml`の変更時にイメージを再ビルド
        - action: rebuild
          path: ./pyproject.toml

次に、開発セットアップでコンテナを実行するにはdocker compose watchを実行します。

完全な例はuv-docker-exampleプロジェクトで確認できます。

最適化

バイトコードのコンパイル

バイトコードへのPythonソースファイルのコンパイルは、通常、インストール時間が増加する代わりに起動時間を改善するため、プロダクションイメージにとって望ましいです。

バイトコードのコンパイルを有効にするには、--compile-bytecodeフラグを使用します:

Dockerfile
RUN uv sync --compile-bytecode

または、UV_COMPILE_BYTECODE環境変数を設定して、Dockerfile内のすべてのコマンドがバイトコードをコンパイルするようにします:

Dockerfile
ENV UV_COMPILE_BYTECODE=1

キャッシュ

キャッシュマウントを使用して、ビルド間のパフォーマンスを向上させることができます:

Dockerfile
ENV UV_LINK_MODE=copy

RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync

デフォルトのUV_LINK_MODEを変更すると、キャッシュと同期ターゲットが別のファイルシステム上にあるため、ハードリンクを使用できないことに関する警告が表示されなくなります。

キャッシュをマウントしていない場合、--no-cacheフラグを使用するかUV_NO_CACHEを設定して、イメージサイズを削減できます。

Note

キャッシュディレクトリの場所は、コンテナ内でuv cache dirコマンドを実行して確認できます。

代わりに、一定の場所に設定することもできます:

Dockerfile
ENV UV_CACHE_DIR=/opt/uv-cache/

中間レイヤー

uvを使用してプロジェクトを管理している場合、--no-installオプションを使用して推移的依存関係のインストールを独自のレイヤーに移動することで、ビルド時間を改善できます。

uv sync --no-install-projectはプロジェクトの依存関係をインストールしますが、プロジェクト自体はインストールしません。プロジェクトは頻繁に変更されますが、その依存関係は一般的に静的であるため、これは大きな時間の節約になります。

Dockerfile
# uvのインストール
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# 作業ディレクトリを`app`ディレクトリに変更
WORKDIR /app

# 依存関係のインストール
RUN --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    uv sync --frozen --no-install-project

# プロジェクトをイメージにコピー
ADD . /app

# プロジェクトの同期
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --frozen

pyproject.tomlはプロジェクトのルートと名前を識別するために必要ですが、プロジェクトの_内容_は最終的なuv syncコマンドまでイメージにコピーされません。

Tip

ワークスペースを使用している場合、プロジェクト_および_ワークスペースメンバーを除外する--no-install-workspaceフラグを使用します。

同期から特定のパッケージを除外する場合は、--no-install-package <name>を使用します。

非編集可能なインストール

デフォルトでは、uvはプロジェクトとワークスペースメンバーを編集可能モードでインストールし、ソースコードへの変更が環境に即座に反映されるようにします。

uv syncおよびuv runはどちらも--no-editableフラグを受け入れ、uvにプロジェクトを非編集可能モードでインストールするよう指示し、ソースコードへの依存を削除します。

マルチステージDockerイメージのコンテキストでは、--no-editableを使用して、あるステージから同期された仮想環境にプロジェクトを含め、最終イメージには仮想環境のみ(ソースコードは含まない)をコピーできます。

例:

Dockerfile
# uvのインストール
FROM python:3.12-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# 作業ディレクトリを`app`ディレクトリに変更
WORKDIR /app

# 依存関係のインストール
RUN --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    uv sync --frozen --no-install-project --no-editable

# プロジェクトを中間イメージにコピー
ADD . /app

# プロジェクトの同期
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --frozen --no-editable

FROM python:3.12-slim

# ソースコードではなく環境をコピー
COPY --from=builder --chown=app:app /app/.venv /app/.venv

# アプリケーションの実行
CMD ["/app/.venv/bin/hello"]

一時的にuvを使用する

最終イメージでuvが不要な場合、各呼び出しでバイナリをマウントできます:

Dockerfile
RUN --mount=from=ghcr.io/astral-sh/uv,source=/uv,target=/bin/uv \
    uv sync

pipインターフェースの使用

パッケージのインストール

コンテナはすでに隔離されているため、このコンテキストでシステムPython環境を安全に使用できます。--systemフラグを使用してシステム環境にインストールします:

Dockerfile
RUN uv pip install --system ruff

デフォルトでシステムPython環境を使用するには、UV_SYSTEM_PYTHON変数を設定します:

Dockerfile
ENV UV_SYSTEM_PYTHON=1

代わりに、仮想環境を作成してアクティブ化できます:

Dockerfile
RUN uv venv /opt/venv
# 仮想環境を自動的に使用
ENV VIRTUAL_ENV=/opt/venv
# エントリーポイントを環境の先頭に配置
ENV PATH="/opt/venv/bin:$PATH"

仮想環境を使用する場合、uvの呼び出しから--systemフラグを省略する必要があります:

Dockerfile
RUN uv pip install ruff

要件のインストール

要件ファイルをインストールするには、コンテナにコピーします:

Dockerfile
COPY requirements.txt .
RUN uv pip install -r requirements.txt

プロジェクトのインストール

要件と一緒にプロジェクトをインストールする場合、要件のコピーをプロジェクト自体のコピーから分離することがベストプラクティスです。これにより、プロジェクトの依存関係(頻繁には変更されない)をプロジェクト自体(非常に頻繁に変更される)とは別にキャッシュできます。

Dockerfile
COPY pyproject.toml .
RUN uv pip install -r pyproject.toml
COPY . .
RUN uv pip install -e .