1. はじめに
FastAPIの開発環境をPythonの型付け(型ヒント)の恩恵を厳し目に受けながら開発したい。
そしてそれらの設定が反映されたDockerの開発環境をつくってホストの環境を汚さないようにしたい。
さらにVS CodeのRemote Containerを使うことでDockerの開発環境に接続して開発できる状態にしたい。
という動機から始まっています。
1-1.背景
上記を実現するためにFastAPIの環境構築について調査していると、「個人的にこの設定がスタンダートな最小構成だよね」をまとめるに苦労したのでこの際まとめておくことにしました。
以下が反映される最小構成を目指します。
- Pythonで型付け(型ヒント)の恩恵をうける設定が入っていること
- FastAPIの自動チューニングの設定が入っていること
- 日本語化やタイムゾーンなどの基本的な設定がDockerイメージに含まれていること
- これらをVS CodeのRemote Containerで開発できる設定になっていること
1-2. 前提条件
- Remote ContainerはVS Codeにインストール済み
- Docker Descktopはインストール済み
- 今回はPython 3.9
- FastAPIの公式イメージの最新版が執筆時点で3.9なので
2. 構築手順
とにかく動かしたい方は、以下の手順をコピペすれば動きます。
2-1. ディレクトリ構成
以下のように配置します。fastapi-test
がworkspaceになるディレクトリです。
fastapi-test
├─ .devcontainer
└─ devcontainer.json
├─ app
└─ main.py
├─ .dockerignore
├─ Dockerfile
└─ requirements.txt
2-2. 各ファイルの内容
devcontainer.json
devcontainer.json
はRemote Containerを使うときの設定ファイルです。
公式ドキュメントどおり .devcontainer/devcontainer.json
に配置します。
VS CodeのRemote Containerを立ち上げたときに、以下の動作になるように設定しています。
- Lintが動作すること
- 型ヒントが厳しめに動作すること
- ただし外部ライブラリについては余計な型チェックが入らないように動作すること
- TypeScriptと違って型定義が提供されていないライブラリは多い
-
mypy.ini
をおいても解決しないのでdiagnosticSeverityOverrides
に設定を書くのがミソです
また、root
で作業できないように appuser
でコンテナに接続するようにします。
後述のDockerfile内でappuser
を作成しています。
{
"name": "fastapi-test",
"build": {
"dockerfile": "../Dockerfile",
"context": "..",
},
"runArgs": [ "--name", "fastapi-test"],
"settings": {
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.linting.pylintArgs": [
"--disable", "E1101,E0213,R0201",
"--extension-pkg-whitelist", "pydantic",
],
"python.linting.mypyEnabled": true,
"python.analysis.typeCheckingMode": "strict",
"python.analysis.diagnosticSeverityOverrides": {
"reportMissingTypeStubs": "none",
"reportUnknownParameterType": "none",
"reportUnknownMemberType": "none",
"reportUnknownArgumentType": "none",
"reportUnknownVariableType": "none"
}
},
"extensions": [
"ms-python.python",
"njpwerner.autodocstring",
"ms-python.vscode-pylance",
],
"postCreateCommand": "pip install -U mypy pylint",
"remoteUser": "appuser"
}
main.py
公式ドキュメント の内容をそのまま拝借します。
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
.dockerignore
主にpython周りの余計なファイルなどがビルドに含まれないように設定しておきます
Dockerfile
README.md
*.pyc
*.pyo
*.pyd
__pycache__
.pytest_cache
Dockerfile
冒頭のとおり個人的にスタンダートな最小構成を書いています
# 公式のイメージ ちなみに80がEXPOSEされている
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
# python周りの設定
# pycを生成しない、および 標準出力と標準エラー出力がすぐに出力されるようにする
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
# 日本語化周りの設定
RUN apt-get update && apt-get install -y locales && locale-gen ja_JP.UTF-8
ENV LANG=ja_JP.UTF-8 TZ=Asia/Tokyo
# お好みで
# RUN apt-get install -y vim less procps libssl-dev curl
# 専用のユーザーを作成してbashに変更する
RUN useradd --create-home appuser && chsh -s /bin/bash appuser
USER appuser
WORKDIR /home/appuser
# パッケージをインストール
COPY ./requirements.txt .
RUN pip install --upgrade pip setuptools \
&& pip install --no-cache-dir -r ./requirements.txt
# アプリケーションのソース
COPY ./app/ ./
requirements.txt
お好みで
3. 動作確認
3-1. VS CodeのRemote Containerを起動する
fastapi-test
ディレクトリをVS Codeで開いたら画面左下にある緑色のアイコンを押して、メニューの中から Open Folder in Container
を開きます。
Dockerイメージのビルドが始まるのでしばらく待ちます。
ビルドが完了すると、Pylanceの拡張を有効にするためのポップアップが表示されるので Yes
を押してVS Codeを開き直します。
3-2. アプリケーションを起動する
VS Codeからターミナルを開いて(ちなみにBashになっています)、uvicorn app.main:app --host 0.0.0.0 --reload
でアプリケーション(main.py
)を起動します。
リンクを開いて {"Hello":"World"}
が表示されていればOKです。
また、 FastAPIの公式ドキュメントのとおり、APIがたたけることも確認しておきます。
もちろん公式の通り/docsを開けばSwagger UIのドキュメントを確認できます。
ちなみに、↑ではホストの8000番ポートが接続していますが、これはRemote Containerが自動的にフォワーディングする機能があるためです(便利ですね)。
以上