当サイトは、アフィリエイト広告を利用しています

【Docker × FastAPI 】uvicornの起動方法について

作成日:2025月02月24日
更新日:2025年02月24日

fastapi製のアプリケーションを動かす際によく使われる ASGI(Synchronous Server Gateway Interface)サーバのuvicornの
起動方法を調べてたのでまとめる

uvicornの起動方法を大きく

  • コマンドラインから起動する
  • Pythonスクリプトから起動する

の2種類がある。

コマンドラインから起動する

uvicornをコマンドラインから起動する方法

起動コマンドサンプル

dockerコンテナ内でfastapiアプリケーションをuvicornで起動する場合の
起動コマンドサンプル

コマンドライン起動
uvicorn app.asgi:app --reload --host 0.0.0.0 --port 8000

細かく解説すると

app.asgi:app

fastapiのアプリケーションインスタンスのパスを指定

--reload

ソースに変更があった場合に再起動する
※いわゆるホットリロード

--hostと--port

  • IPアドレスの設定 → 0.0.0.0 にすれば、コンテナの外(ホストOS)からアクセス可能になる
  • ポート番号の設定 → -p 8000:8000 でホストとコンテナのポートを紐付ける
  • この2つを組み合わせると → http://localhost:8000 でホストOSからアクセスできる

ちなみにhost指定なしで起動すると127.0.0.1(ローカルホスト)で起動してしまう。
127.0.0.1(ローカルホスト)は「コンテナ内部の 127.0.0.1 で待ち受ける」ことであり
ホストOSはコンテナの外なのでアクセスできない。 ※IPアドレスを0.0.0.0(すべてのIPアドレスを受け付ける) ocalhost:8000 でコンテナ内のアプリにアクセスできる

コマンドライン起動の利点

コマンドライン起動の利点としては下記がある

シンプルで簡単

  • ターミナルから1行で実行することができる
  • プログラムを変更せずにコマンドラインから実行することができる
  • コマンドをVSCodeのタスクに登録してショートカット実行も可能

オプションのカスタマイズが簡単

  • --portや--hostなどを都度変更がしやすい

Pythonスクリプトから起動する

uvicornをPython内で起動する方法

起動スクリプトサンプル

dockerコンテナ内でfastapiアプリケーションをuvicornで起動する場合の
起動スクリプトのサンプル

start_uvicorn.py
import uvicorn
from uvicorn_config import config
if __name__ == "__main__":
# uvicorn起動
uvicorn.run(
"asgi:app",
host="0.0.0.0",
port=8000,
reload=True,
)

それぞれの引数の意味については
コマンドライン起動と同じ。

スクリプト起動の利点

スクリプト起動の利点としては下記がある

Pythonコード内で条件分岐やカスタマイズが可能

  • Pythonコードなので環境変数に合わせた条件分岐だと複雑なカスタマイズができる

スクリプトの一部として動作できる

  • 他のpython処理(DB初期化やログ処理など)と組み合わせて起動処理を実行できる

コマンドライン起動をfastapi製REST APIでの実装

fastap製のREST APIでuvicornのコマンドライン起動を試してみる

プロジェクト構成

プロジェクト構成
.
|-- app
| |-- __init__.py
| |-- asgi.py
| |-- endpoints.py
| `-- main.py
|-- docker-compose.yml
|-- dockerfile
`-- requirements.txt

簡易なfastapi製のREST APIをdockerコンテナ上で作成する

requirements.txt

requirements.txt
fastapi==0.115.6
uvicorn[standard]==0.34.0

最低限必要なパッケージを設定

dockerfile

dockerfile
FROM python:3.12
# PYTHONPATHの設定
ENV PYTHONPATH=/workspace/app
# workspaceディレクトリ作成、移動
WORKDIR /workspace
# プロジェクトディレクトリにコピー
COPY requirements.txt /workspace
# 必要パッケージのインストール
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

requirements.txtで設定したパッケージをインストールしたdockerイメージを
作成する。

docker-compose.yml

docker-compose.yml
version: "3"
services:
uvicorn-start:
container_name: "uvicorn-start"
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/workspace
tty: true
ports:
- 8000:8000 # ホストマシンのポート8000を、docker内のポート8000に接続する
# command:
# ["uvicorn", "asgi:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]

dockerfileで作ったイメージを元にコンテナを作成する
コンテナ起動と同時にuvicornを起動する場合は「command」部分のコメントアウトを解除する
手動で起動や停止したい場合は、コメントアウトのままにする

app/main.py

main.py
from fastapi import FastAPI
import logging
import endpoints as endpoints
def create_app():
# アプリケーションインスタンスの作成
app = FastAPI()
# ルーティング設定
app.include_router(endpoints.router)
return app

アプリケーションの初期化処理を行うモジュール

app/asgi.py

asgi.py
from main import create_app
app = create_app()

FastApiアプリケーションをASGIサーバーで起動するための エントリーポイントとなるモジュール
コマンドライン起動のオプションでこのモジュールのapp(fastapiアプリケーションインスタンス)を指定する

app/endpoints.py

endpoints.py
import logging
from fastapi import APIRouter
from fastapi.responses import JSONResponse
router = APIRouter()
# ディクショナリ
users = [
{"user_id": "1", "name": "Tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 501},
{"user_id": "4", "name": "kyogoku", "age": 70}
]
# ユーザー一覧を取得
@router.get("/")
async def get_users():
return JSONResponse(status_code=211, content=users)

エンドポイントを管理するモジュール。 GETのエンドポイントを作成しておく

コンテナ作成

docker-composeを実行してコンテナを作成する

コンテナ作成
$ docker compose up -d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e575d48ad46 fastapi_uvicorn_start_pattern-uvicorn-start "uvicorn asgi:app --…" 21 seconds ago Up 14 seconds 0.0.0.0:8000->8000/tcp uvicorn-start

コンテナにアタッチする

アタッチ
$ docker exec -it uvicorn-start sh
#

上記ではコマンドラインからコンテナにアタッチしてるが
VSCodeからリモートでコンテナに接続する場合はVSCodeの拡張機能で

  • Dev Containers(ms-vscode-remote.remote-containers)
  • Docker(ms-azuretools.vscode-docker)

のどちらかを使用すれば、コンテナ内をVSCodeから操作できる ※この拡張機能はホスト側のVSCodeでインストールして使う

コンテナ内でコマンドライン起動

コマンドライン起動
$ docker exec -it uvicorn-start sh
# 起動
# uvicorn asgi:app --reload --host 0.0.0.0 --port 8000
INFO: Will watch for changes in these directories: ['/workspace']
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process [13] using WatchFiles
INFO: Started server process [15]
INFO: Waiting for application startup.
INFO: Application startup complete.
# 停止
^CINFO: Shutting down
INFO: Waiting for application shutdown.
INFO: Application shutdown complete.
INFO: Finished server process [20]
INFO: Stopping reloader process [18]

正常に起動する。
停止する時はctrl + c で止める

起動中にホスト側からcurlコマンドでGETリクエストを投げるとレスポンスが返ってくる

リクエスト
$ curl -i -X GET http://localhost:8000
HTTP/1.1 211
date: Sat, 22 Feb 2025 15:42:18 GMT
server: uvicorn
content-length: 168
content-type: application/json
[{"user_id":"1","name":"Tujimura","age":11},{"user_id":"2","name":"mori","age":20},{"user_id":"3","name":"shimada","age":501},{"user_id":"4","name":"kyogoku","age":70}]

VScodeのタスクに登録する

毎回コマンドを打つのが面倒であれば、上記でも書いたが
docker-compose.ymlでコンテナ作成時に起動する、または
VScodeのタスクに登録すればショートカット起動することができる。

VScodeのタスク登録

VSCodeのタスクに登録しておく。手順は下記の通り

  • 「F1」でコマンドパレットを開く
  • 「テンプレートからtask.json」を生成
  • 「Othes」を選択※後で書き換えるのでなんでもいい

上記を実行すると.vscode/task.jsonが作成されるので 下記ように書き換える

.vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Run Uvicorn",
"type": "process",
"command": "uvicorn",
"args": [
"asgi:app",
"--reload",
"--host",
"0.0.0.0",
"--port",
"8000"
],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

VScodeのタスクなので、このタスクを実行するためには
コマンドではなく、拡張機能Dev ContainersかDockerを使ってVSCodeからコンテナにアタッチする必要がある

Pythonスクリプト起動をfastapi製REST APIでの実装

次はfastap製のREST APIでuvicornのPythonスクリプト起動を試してみる

プロジェクト構成

プロジェクト構成
.
|-- app
| |-- __init__.py
| |-- asgi.py
| |-- endpoints.py
| `-- main.py
|-- docker-compose.yml
|-- dockerfile
|-- requirements.txt
|-- start_uvicorn.py
`-- uvicorn_config.py

コマンドライン起動と同様に簡易なfastapi製のREST APIをdockerコンテナ上で作成する

requirements.txt

requirements.txt
fastapi==0.115.6
uvicorn[standard]==0.34.0

最低限必要なパッケージを設定

dockerfile

dockerfile
FROM python:3.12
# PYTHONPATHの設定
ENV PYTHONPATH=/workspace/app
# workspaceディレクトリ作成、移動
WORKDIR /workspace
# プロジェクトディレクトリにコピー
COPY requirements.txt /workspace
# 必要パッケージのインストール
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

requirements.txtで設定したパッケージをインストールしたdockerイメージを
作成する。

docker-compose.yml

docker-compose.yml
version: "3"
services:
uvicorn-start:
container_name: "uvicorn-start"
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/workspace
tty: true
ports:
- 8000:8000 # ホストマシンのポート8000を、docker内のポート8000に接続する
entrypoint: ["python", "start_uvicorn.py"]

dockerfileで作ったイメージを元にコンテナを作成する
コンテナ起動時にuvicorn起動用のpythonスクリプトが実行されるように
entrypointで指定する

app配下のモジュール

app配下のモジュールの

  • main.py
  • asgi.py
  • endpoints.py

についてはコンテナ起動と同じのため割愛する。

uvicorn_config.py

uvicorn_config.py
# uvicorn起動設定
config = {
"host": "0.0.0.0",
"port": 8000,
"reload": True,
"log_level": "info"
}

uvicorn起動設定を別モジュールに持たせる

start_uvicorn.py

start_uvicorn.py
import uvicorn
from uvicorn_config import config
if __name__ == "__main__":
# uvicorn起動
uvicorn.run(
"asgi:app",
host=config["host"],
port=config["port"],
reload=config["reload"]
)

uvicorn.runメソッドの引数にuvicorn_configで設定した値を
渡してuvicornを起動する

コンテナ作成

再度コンテナを作成する

コンテナ作成
$ docker compose up -d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3fcab9cdd99d fastapi_uvicorn_start_pattern-uvicorn-start "python start_uvicor…" 44 seconds ago Up 38 seconds 0.0.0.0:8000->8000/tcp uvicorn-start

コンテナ作成後、コンテナのログを見ると

コンテナログ
$ docker logs uvicorn-start
INFO: Will watch for changes in these directories: ['/workspace']
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process [1] using WatchFiles
INFO: Started server process [8]
INFO: Waiting for application startup.
INFO: Application startup complete.

コンテナ起動と同時にuvicornも動いてる

ホストからGETリクエストで動作確認

GETリクエスト
$ curl -i -X GET http://localhost:8000
HTTP/1.1 211
date: Mon, 24 Feb 2025 13:08:30 GMT
server: uvicorn
content-length: 168
content-type: application/json
[{"user_id":"1","name":"Tujimura","age":11},{"user_id":"2","name":"mori","age":20},{"user_id":"3","name":"shimada","age":501},{"user_id":"4","name":"kyogoku","age":70}]

まとめ

fastapiアプリを動かす際によく使うuvicornサーバーの起動方法について
まとめてみた。

ケースバイケースだが、開発中はコマンライン起動で使うことが多い気がする。

新着記事

目次
タグ別一覧
top