前提
- uvがインストールされていること
本編
プロジェクト作成
uv init uv-fastapi -p 3.12
fastapiをインストール
cd uv-fastapi
uv add "fastapi[standard]"
hello.pyをmain.pyにリネームし、ファイルの中身を書き換える
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def root():
return {'message": "Hello World'}
Dockerfile作成
FROM python:3.12-slim-bookworm
ARG DEVELOPMENT=0
# コンテナ内に.venvを作らないようにする環境変数
ENV UV_PROJECT_ENVIRONMENT='/usr/local/'
ENV UV_SYSTEM_PYTHON=1
WORKDIR /app
# NOTE: パッケージを追加したい場合はコメントアウトを解除し、`apt-get install`のパッケージを書き換えてください
#
# RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
# --mount=type=cache,target=/var/lib/apt,sharing=locked \
# apt-get update && \
# apt-get install -y --no-install-recommends \
# default-libmysqlclient-dev \
# build-essential \
# pkg-config
# バージョンを指定してuvをコピー
COPY --from=ghcr.io/astral-sh/uv:0.5.27 /uv /bin/uv
ADD . /app
# Pythonパッケージインストール
RUN \
# ローカル環境は全てのパッケージをインストール
if [ $DEVELOPMENT = 1 ]; then \
uv export --frozen --format requirements-txt > requirements.txt && \
uv pip install -r requirements.txt; \
# ローカルでない環境では開発用パッケージをインストールしない(クラウドにアップロードする場合など)
else \
uv export --frozen --no-dev --format requirements-txt > requirements.txt && \
uv pip install -r requirements.txt; \
fi
CMD ["uvicorn", "main:app", "--reload", "--host=0.0.0.0", "--port=8000"]
compose.yaml作成
compose.yaml
services:
api:
build:
context: .
dockerfile: Dockerfile
args:
DEVELOPMENT: 1
volumes:
- .:/app
- /app/.venv # .vnevを空ディレクトリで上書きする(これがないとローカルの.venvの中身がコンテナの中に追加されちゃうんですよね、.dockerignoreも効果なし、知見求む)
ports:
- '8000:8000'
tty: true
コンテナ起動
docker compose up -d
ブラウザから http://localhost:8000/docs にアクセス
以上
uvの感想
これまではpyenvとvirtualenvで仮想環境を作ってpoetryでパッケージ管理してましたが、uvだけで全て完結できるようになったのでとても楽になりやした。
"uv"だけでググると紫外線が上位ヒットしちゃうのでもっとググラビリティが高い名前にしても良かったんじゃない?とは思う。
Rust製で高速を謳っているけども、パッケージマネージャの速度が問題になったことなんて無いから数秒単位の速度誤差は正直どうでも良いと思ったり思わなかったり。