FastAPI Docker入門|Pythonアプリをコンテナでデプロイするまでをゼロから解説

プログラミング

「FastAPIで作ったAPIを、ちゃんとDockerで動かせるようにしたい」という動機で調べはじめました。Lambda関数としてデプロイする機会が多かったんですが、コンテナイメージとして動かす構成も覚えておきたくて。

この記事では、FastAPIアプリのDockerfile作成からdocker-composeでの起動、開発環境でのホットリロード設定やTipsをまとめています。

この記事でわかること

  • FastAPIのDockerコンテナ化の基本
  • 効率的なDockerfileの書き方(レイヤーキャッシュを活用した高速ビルド)
  • docker-composeでの開発環境構築
  • 開発時のホットリロード設定
  • 本番環境を意識した設定(ワーカー数など)

FastAPIとDockerを組み合わせる理由

FastAPIはそのままuvicornコマンドで起動できますが、チームで使ったり本番環境にデプロイするとなると「どの環境でも同じように動く」保証が欲しくなります。Dockerはそこを解決してくれます。

それと、AWS LambdaもECRのコンテナイメージから関数を作成してデプロイできるようになっていて、「Lambdaもコンテナも同じDockerfileで」という開発スタイルが増えてきた印象です。コンテナイメージとして動かせるようにしておくと、ECS・Lambda・Lightsailなど選択肢が広がるのでやっておいて損はないかなと。

最小構成のFastAPIアプリを作る

最初はシンプルに。以下のディレクトリ構成で進めます。

my-api/
├── app/
│   └── main.py
├── requirements.txt
└── Dockerfile

app/main.pyはこんな感じです。

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello, World!"}

@app.get("/health")
def health_check():
    return {"status": "ok"}

requirements.txtは最小限で。

fastapi[standard]

余談ですが、fastapi[standard]と書くとuvicornなど必要なものがまとめてインストールされるようです。地味に便利です。

Dockerfileを書く

ここが本題です。よく見かける古い書き方と、今の書き方の違いを意識しながら書きました。

FROM python:3.12-slim

WORKDIR /code

COPY ./requirements.txt /code/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app

CMD ["fastapi", "run", "app/main.py", "--port", "80", "--host", "0.0.0.0"]

以前は起動コマンドが uvicorn app.main:app --host 0.0.0.0 --port 80 みたいな書き方が主流でしたが、fastapi run コマンドが使えるようになってかなりシンプルになりました。fastapi run は内部でuvicornを使って動いてくれます。

ポイントをいくつか書いておきます。

  • python:3.12-slimを使う。python:3.12(フル版)より小さくできることが多いです
  • COPYの順番が大事。requirements.txtを先にコピーしてpip installしてから、ソースコードをコピーする。こうすることでコードだけ変更したときにpipのレイヤーキャッシュが使われてビルドが速くなる
  • --no-cache-dirをつけてイメージサイズを削減

レイヤーキャッシュの順番については最初わかってなくて「なんかビルド遅いな」ってなってました。COPY . .を先に書くとコード変更のたびにpipが全部走るので地味につらいです。

ビルドして動かす

Dockerfileが書けたら、ビルドして起動します。

# イメージのビルド
docker build -t my-fastapi-app .

# コンテナの起動(ポート8000→80にマッピング)
docker run -p 8000:80 my-fastapi-app

http://localhost:8000にアクセスして{"message": "Hello, World!"}が返ってくれば成功です。FastAPIの自動生成ドキュメントはhttp://localhost:8000/docsで確認できます。Swagger UIが表示されるので、これを見るたびにちょっとテンション上がります。

docker-composeで管理する

実際の開発ではdocker composeを使うことが多いです。DBを一緒に立ち上げたり、環境変数を管理したりが楽になります。

シンプルなcompose.yamlはこんな感じです(docker composeは既定でcompose.yamldocker-compose.yamlなどを探索してくれます)。

services:
  api:
    build: .
    ports:
      - "8000:80"
    volumes:
      - ./app:/code/app  # 開発時:ホットリロード用にマウント
    environment:
      - ENV=development

起動は docker compose up でOKです。ログを見ながら動かしたいときは docker compose up、バックグラウンドで動かすときは docker compose up -d

ただ、上のvolumesの設定はあくまで開発時用です。本番ではvolumesを外してイメージに焼き込む運用が正しいはず。この使い分けをちゃんと意識するようになったのは割と最近です。

開発環境でホットリロードを使う

コードを変更するたびにコンテナを再起動するのは面倒なので、開発中はホットリロードを使います。

compose.yamlのcommandを上書きする方法が一番シンプルです。

services:
  api:
    build: .
    ports:
      - "8000:80"
    volumes:
      - ./app:/code/app
    command: ["fastapi", "dev", "app/main.py", "--host", "0.0.0.0", "--port", "80"]

fastapi devコマンドがホットリロードモードで起動してくれます。--reloadフラグを自分で渡さなくていいのが地味に便利です。ファイルを変更するとコンテナ内でも自動的に反映されます。

本番を意識するなら:uvicornワーカー数の設定

EC2やLightsailに乗せるような場合、複数ワーカーを動かしたほうがスループットが上がることがあります。fastapi run--workersオプションを渡すだけです。

CMD ["fastapi", "run", "app/main.py", "--port", "80", "--host", "0.0.0.0", "--workers", "4"]

ただしLambdaでの挙動や、ECSなどのオーケストレーション環境で「ワーカーを増やす」か「コンテナを増やす」かの考え方は、要件や構成によって変わります。正直このあたりの正解はまだ自分の中で消化しきれていないので、もう少し実戦で試したいところです。

最終的なファイル構成まとめ

整理するとこんな構成になります。

my-api/
├── app/
│   └── main.py
├── compose.yaml
├── requirements.txt
└── Dockerfile

最終的なDockerfile(本番用):

FROM python:3.12-slim

WORKDIR /code

COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app

CMD ["fastapi", "run", "app/main.py", "--port", "80", "--host", "0.0.0.0"]

開発用compose.yaml

services:
  api:
    build: .
    ports:
      - "8000:80"
    volumes:
      - ./app:/code/app
    command: ["fastapi", "dev", "app/main.py", "--host", "0.0.0.0", "--port", "80"]

このセットがあれば「ローカルで開発→イメージをビルドして本番へ」という流れが一通りできるようになります。

※この記事にはプロモーションが含まれます

ちなみに、お名前.com レンタルサーバー(WordPressに特化した高速レンタルサーバー。月額990円〜、独自ドメイン実質0円)も気になっています。お名前.com レンタルサーバー

まとめ

  • FastAPIはDockerコンテナ化することで、環境の差異をなくして本番デプロイがしやすくなる
  • Dockerfileはレイヤーキャッシュを活用するために、requirements.txtを先にコピーすることが重要
  • fastapi runuvicornより簡潔で、新しいバージョンではこちらが推奨される
  • docker composeで開発環境と本番環境の設定を分けると、管理しやすくなる
  • 開発時はfastapi devでホットリロード、本番時はfastapi runで起動することで、開発体験と本番の安定性の両立が可能

参考になったらクリックしてもらえると嬉しいです!

Blogmura ProgrammingProgramming Ranking
タイトルとURLをコピーしました