DockerでFastAPI環境構築(HelloWorldまで)
FastAPI環境構築
リンク
使用技術
環境
- Docker
- Python 3.12.3(執筆時最新)
- nginx(webサーバー)
DB
- MySQL 8系
- SQLModel(ORマッパー)
- alembic(マイグレーション管理)
ライブラリ管理
- poetry
構成はシンプルでnginxをwebサーバーとして配置して、Uvicormをアプリケーションサーバーにします。
ディレクトリ作成
最低限のディレクトリを作成していきます。
project_root
├── _docker
│ ├── nginx
│ │ └── nginx.conf
│ └── python
│ └── Dockerfile
├── src
│ └── main.py
├── .env
├── pyproject.toml
└── docker-compose.yml
/_docker/python/Dockerfile(仮なので最後に再編集します)
pythonのDockerfileです。ライブラリ管理にpoetryを使用するのと、テストDBにsqliteを使用するので、ここでインストールしています。
FROM python:3.12.3
SHELL ["/bin/bash", "-c"]
# 作業ディレクトリの設定
WORKDIR /src
RUN apt-get update && \
apt-get install -y build-essential libffi-dev && \
apt-get install -y sqlite3
RUN pip install --upgrade pip
# 必要なファイルのコピー
COPY ./pyproject.toml /src/pyproject.toml
# Poetryのインストール
RUN curl -sSL https://install.python-poetry.org | python -
ENV PATH="/root/.local/bin:$PATH"
# Poetryの設定と依存関係のインストール
RUN poetry config virtualenvs.create false && \
poetry install --no-interaction --no-root
# アプリケーションの起動コマンドを設定
ENTRYPOINT ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--reload"]
/_docker/nginx/nginx.conf
FastAPIへ繋ぐためのプロキシ設定です。
events {}
http {
server {
listen 80;
location / {
proxy_pass http://fastapi:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
/docker-compose.yml
特段、普通の設定かと思います。volumeを使用して永続化を行なったり、MySQLのDBを作成したりしています。
version: '3.8'
services:
fastapi:
build:
context: .
dockerfile: _docker/python/Dockerfile
volumes:
- .:/src
- bash-data:/root/.local/bin
- python-lib-data:/usr/local/lib/
ports:
- "8000:8000"
depends_on:
- mysql
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./_docker/nginx/nginx.conf:/etc/nginx/nginx.conf
depends_on:
- fastapi
mysql:
image: mysql:latest
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_DATABASE: 'fastapi_db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- "3334:3306"
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
bash-data:
python-lib-data:
/src/main.py
とりあえず疎通確認ができるように公式のコードをコピペ
from fastapi import FastAPI
app = FastAPI()
.get("/")
async def root():
return {"message": "Hello World"}
/pyproject.toml
poetry initで自動作成できるが、dockerでやるのも手間なので手動で作成しておくのが無難だと思います。今回も手動で作成します。(最低限のライブラリのみ記載)
[tool.poetry]
name = "my_project"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.12"
fastapi = "^0.111.0"
uvicorn = "^0.29.0"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
ビルドと起動
docker compose up --build -d
下記にアクセスして、接続できたら環境の構築は完了です。
このままだとライブラリのバージョンが環境によって不揃いになってしまいます。
なので、poetry.lockファイルを生成しましょう。
コンテナに入る
docker compose exec -it fastapi /bin/bash
コンテナ内でロックファイルを生成
root:/src# poetry lock
ルートにロックファイルが生成されます。
project_root
├── _docker
│ ├── nginx
│ │ └── nginx.conf
│ └── python
│ └── Dockerfile
├── src
│ └── main.py
├── .env
├── pyproject.toml
├── poetry.lock <-これが作成されます。
└── docker-compose.yml
ビルドする際にもlockファイルをコンテナにコピーするようにします。
FROM python:3.12.3
SHELL ["/bin/bash", "-c"]
# 作業ディレクトリの設定
WORKDIR /src
RUN apt-get update && \
apt-get install -y build-essential libffi-dev && \
apt-get install -y sqlite3
RUN pip install --upgrade pip
# 必要なファイルのコピー
COPY ./pyproject.toml /src/pyproject.toml
COPY ./poetry.lock /src/poetry.lock // 追加
# Poetryのインストール
RUN curl -sSL https://install.python-poetry.org | python -
ENV PATH="/root/.local/bin:$PATH"
# Poetryの設定と依存関係のインストール
RUN poetry config virtualenvs.create false && \
poetry install --no-interaction --no-root
# アプリケーションの起動コマンドを設定
ENTRYPOINT ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--reload"]
再ビルド
docker compose build --no-cache
docker compose up -d
キャッシュあってもいいなら
docker compose up --build -d
再度、コンテナを起動してlocalhost:8000にアクセス
ブラウザに下記が表示されればOKです。
{"message":"Hello World"}
これで基本的な環境はできたかと思います。
コマンドの簡略化
怠惰なので、長いコマンドをいちいち打ちたくないです。
例えばコンテナ内に入るときも
docker compose exec -it fastapi /bin/bash
だるすぎます。
なので、makeコマンドで下記のように簡略化します。
make api
まずはmakeコマンドをローカルとコンテナ内で使用することを考えます。
makefileにはincludeが備わっていることに加え、条件分岐も使用できます。
この辺を応用して、ローカルとコンテナ内でmakeコマンドを別管理していきます。
まずは本体のmakeファイルの作成をローカルで行います。
/makefile
ifeq ($(MAKE_ENV), container)
include makefile.container
else
include makefile.local
endif
環境変数MAKE_ENVに値を持たせて、環境によってinclude先を分けます。
Dockerfileの修正
FROM python:3.12.3
SHELL ["/bin/bash", "-c"]
# 作業ディレクトリの設定
WORKDIR /src
RUN apt-get update && \
apt-get install -y build-essential libffi-dev && \
apt-get install -y sqlite3
RUN pip install --upgrade pip
# 必要なファイルのコピー
COPY ./pyproject.toml /src/pyproject.toml
COPY ./poetry.lock /src/poetry.lock
# Poetryのインストール
RUN curl -sSL https://install.python-poetry.org | python -
# 環境変数の設定
ENV MAKE_ENV=container // 追加
ENV PATH="/root/.local/bin:$PATH"
# Poetryの設定と依存関係のインストール
RUN poetry config virtualenvs.create false && \
poetry install --no-interaction --no-root
# アプリケーションの起動コマンドを設定
ENTRYPOINT ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--reload"]
ここからは実際のコマンドが記載されたmakeファイルを環境ごとに作成します。
- makefile.local
- makefile.container
/makefile.local
.PHONY: help print build-local up down api
.DEFAULT_GOAL := help
print: ## 分岐テスト用
echo "ローカル"
build: ## Build docker image to local
docker compose build --no-cache
up: ## Start docker container
docker compose up -d
down: ## Stop docker container
docker compose down
api: ## Run python container
docker compose exec -it fastapi /bin/bash
/makefile.container
.PHONY: help print
.DEFAULT_GOAL := help
print: ## 分岐テスト用
echo "コンテナ"
これで完了です。
再ビルドしましょう
make build
下記のように環境によって同じコマンドでも分けて使用できれば完了です。
ローカル
make print
//出力
echo "ローカル"
ローカル
コンテナ
make api
//出力
docker compose exec -it fastapi /bin/bash
make print
// 出力
echo "コンテナ"
コンテナ
poetryやこの後(記載予定)のマイグレーションコマンドなど真価を発揮するのでmakeファイルは作成しておいて損はないと思います。
Discussion