2026年4月21日火曜日

pipenv から uv に移行する

pipenv から uv に移行する

概要

自分のプロジェクトを pipenv から uv に置き換えたので手順を紹介します

環境

  • macOS 26.3.1
  • Python 3.12.13
  • uv 0.11.7

流れ

  1. pyproject.toml の作成
  2. Dockerfile の修正

python 準備

  • cat .python-version
3.12.13

uv インストール

  • pip install uv

pyproject.toml の作成

[project]
name = "ai-gallery"
version = "0.1.0"
description = "AI Gallery application"
requires-python = ">=3.12"
dependencies = [
    "flask",
    "google-cloud-storage",
    "redis",
    "gunicorn",
    "google-genai",
    "pillow",
    "py-vapid",
    "pywebpush",
]

[dependency-groups]
dev = [
    "black",
    "isort",
    "pyright",
    "pytest",
    "bandit",
]

[tool.black]
line-length = 88
target-version = ["py312"]

[tool.isort]
profile = "black"
line_length = 88

[tool.pyright]
pythonVersion = "3.12"

uv sync

  • uv sync

これで uv.lock が作成されます
仮想環境のパスはプロジェクト直下の .venv に作成されます

Dockerfile 修正

pipenv -> uv に変更します

diff --git a/Dockerfile b/Dockerfile
index 499f280..4ec6df7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,12 +1,16 @@
 FROM python:3.12.13-alpine3.23
 
-COPY . /home
 WORKDIR /home
 
-RUN pip install pipenv
-RUN pipenv install
+COPY pyproject.toml uv.lock ./
+
+RUN --mount=type=cache,target=/root/.cache/pip \
+    pip install uv && \
+    uv export --no-dev | pip install --no-cache-dir -r /dev/stdin
+
+COPY . .
 
 ENV WAIT=on
 ENV MODE=1
 
-CMD ["pipenv", "run", "python", "app.py"]
+CMD ["python", "app.py"]

今回は system 環境にインストールするようにしています

uv sync でも以下のような流れで動作するのでこの当たりは好きなように修正してください

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install uv && \
    uv sync --frozen --no-install-project --no-dev
CMD ["uv", "run", "--no-sync", "gunicorn", "-w", "1", "-b", "0.0.0.0:8080", "app:app"]

--no-sync オプションは実行時に uv sync を実行しないための設定です

一応 docker build -> run して動作確認しておくといいでしょう

README 修正

pipenv で実行している部分を uv に書き換えます
例えば以下のような部分を書き換えていきます

-- pipenv install -d
+- uv sync --all-groups
-- pipenv run isort . && pipenv run black . && pipenv run pyright . && npm run format
+- uv run isort . && uv run black . && uv run pyright . && npm run format
-- pipenv run pytest test/ && pipenv run bandit -r . && REDIS_PASSWORD="" pipenv run gunicorn -w 1 -b 0.0.0.0:8080 app:app
+- uv run pytest test/ && uv run bandit -r . && REDIS_PASSWORD="" uv run gunicorn -w 1 -b 0.0.0.0:8080 app:app
-- pipenv requirements > requirements.txt
+- uv export > requirements.txt

.dockerignore 修正

node_modules/
.venv/

compose.yaml 修正

pipenv -> uv のコマンド修正をします

command: pipenv run python check_new_message.py

command: uv run python check_new_message.py

各種シェルスクリプトの修正

あれば修正します
同様に pipenv -> uv で OK です

Github Actions 修正

各種 yaml ファイルを修正しましょう

diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 50d8f31..48e8a98 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -16,11 +16,11 @@ jobs:
         uses: actions/setup-python@v5
       - name: Install dependencies
         run: |
-          python -m pip install --upgrade pipenv
-          pipenv install -d
+          python -m pip install --upgrade uv
+          uv sync --all-groups
       - name: Lint with isort
         run: |
-          pipenv run isort --check --diff .
+          uv run isort --check --diff .
       - name: Lint with black
         run: |
-          pipenv run black --check .
+          uv run black --check .

実際にアクションを実行して動作確認しましょう

vscode の設定の修正

  • .vscode/settings.json
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8a2fea7..1bd2c9b 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,3 @@
 {
-  "python-envs.defaultEnvManager": "ms-python.python:pipenv",
   "python-envs.pythonProjects": []
 }

これでプロジェクト配下にある .venv を自動で読み込んでくれます

.env ファイルを使っている場合の注意事項

  • uv run --env-file .env

のように命じ的に指定しないと読み込んでくれないので注意しましょう

移行後

  • Pipfile と Pipfile.lock の削除
  • .isort.cfg の削除
  • pip uninstall pipenv
  • venv の削除
    • rm -rf ~/.local/share/virtualenvs/ai-gallery-nT0ArqSL
  • pipenv コマンドがプロジェクト内で使われていないか確認
    • git grep 'pipenv'
  • GAE などにもデプロイしている場合は動作確認
uv export > requirements.txt
gcloud app deploy -q

最後に

アプリ自体を修正するのは簡単ですが CI や各種スクリプトで使われているコマンドを書き換えるのが面倒かなという印象です

2026年4月6日月曜日

Dockerfile の RUN では --mount を使おう

Dockerfile の RUN では --mount を使おう

概要

ビルドを高速化しましょう

環境

  • macOS 26.3.1
  • docker 29.3.1

FROM python:3.12.11-alpine3.21

# 必要なパッケージをインストール
RUN apk add --no-cache nodejs npm

COPY . /home
WORKDIR /home

RUN pip install pipenv
RUN pipenv install

ENV REDIS_HOST=redis

# ミニファイ用ツールをインストール
RUN npm install -g clean-css-cli uglify-js

# CSS / JS をミニファイ
RUN uglifyjs static/js/fontawesome-all.min.js -o static/js/fontawesome-all.min.js
RUN cleancss -o static/css/footer.css static/css/footer.css

CMD ["pipenv", "run", "gunicorn", "-w", "1", "-b", "0.0.0.0:8080", "app:app"]

# syntax=docker/dockerfile:1.7

FROM python:3.12.11-alpine3.21

# 必要なパッケージ
RUN apk add --no-cache nodejs npm

WORKDIR /home

# -------------------------
# ① 依存関係だけ先にコピー(キャッシュ効かせる)
# -------------------------
COPY Pipfile Pipfile.lock ./

# pipenv + cache mount
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install pipenv && \
    pipenv install --deploy --system

# -------------------------
# ② npmツール(キャッシュ効かせる)
# -------------------------
RUN --mount=type=cache,target=/root/.npm \
    npm install -g clean-css-cli uglify-js

# -------------------------
# ③ アプリ本体(最後にコピー)
# -------------------------
COPY . .

ENV REDIS_HOST=redis

# -------------------------
# ④ minify(tmpfsで高速化&不要データ残さない)
# -------------------------
RUN --mount=type=tmpfs,target=/tmp \
    uglifyjs static/js/fontawesome-all.min.js -o static/js/fontawesome-all.min.js && \
    cleancss -o static/css/footer.css static/css/footer.css

CMD ["gunicorn", "-w", "1", "-b", "0.0.0.0:8080", "app:app"]

最後に

今回はライブラリのインストールなどに使いましたが一時的な認証情報を渡すときにも使えます