LoginSignup
8
8

More than 1 year has passed since last update.

FastAPI + MySQL + Dockerを利用したAPI開発方法 メモ

Posted at
  • PythonのAPI構築用フレームワークFastAPIとMySQL、Dockerを利用したAPI開発方法についてメモする。

FastAPIとは

  • Pythonを使ったAPI構築のためのフレームワーク(FlaskやDjangoに類する)

  • Python3.6以上で動作する。

  • 特徴

    • 実装が手軽。
    • 動作が早い。
    • Swagger式のAPI仕様書を作成してくれる。

    など

構成

fastapi_test    __ be   - api   - db.py
                |   |           - main.py
                |   |           - model.py
                |   L_  Dockerfile
                |   L_  requirements.txt
                |
                L_ db   __  data
                |   |
                |   L____   initdb.d    __ create_test_user_table.sql
                |   |           L_________ init_test_user.sql
                |   L____   my.cnf
                |
                L_ docker-compose.yml

docker-compose.yml

version: "3"

services:
  db:
    image: mysql:5.7
    container_name: db
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: sample_db
      MYSQL_USER: mysqluser
      MYSQL_PASSWORD: mysqlpass
    volumes:
      - ./db/data:/var/lib/mysql
      - ./db/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./db/initdb.d:/docker-entrypoint-initdb.d
    ports:
      - 3308:3308
    command: --port 3308
    tty: true

  api:
    depends_on:
      - db
    container_name: "api"
    build: ./be
    ports:
      - "8000:8000"
    volumes:
      - ./be/api:/usr/src/server

データベース(db)

create_test_user_table.sql

  • test_userテーブル作成用
CREATE TABLE test_user (
    id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(30) NOT NULL,
    email VARCHAR(128) NOT NULL,
    PRIMARY KEY (id)
);

init_test_user.sql

  • 初期データ登録用
INSERT INTO test_user (name, email) VALUES ("tanaka taro", "tanaka.taro@example.com");
INSERT INTO test_user (name, email) VALUES ("yamada hanako", "yamada.hanako@example.com");

my.cnf

  • DB文字コード設定
[mysqld]   
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake

[mysqldump]
default-character-set=utf8mb4

[client]
default-character-set=utf8mb4

API(be)

Dockerfile

  • 依存ライブラリのインストールとmain編集時のリロードオプションを指定する。
FROM python:3.7

WORKDIR /usr/src/server
ADD requirements.txt .
RUN pip install -r requirements.txt

CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]

requrements.txt

  • FastAPI用ライブラリ(上2つ)とMySQL接続用ライブラリ(下2つ)を指定する。
uvicorn
fastapi
mysqlclient
sqlalchemy

db.py

  • DB接続設定
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session

host = "db:3308"
db_name = "sample_db"
user = "mysqluser"
password = "mysqlpass"

DATABASE = 'mysql://%s:%s@%s/%s?charset=utf8' % (
    user,
    password,
    host,
    db_name,
)

ENGINE = create_engine(
    DATABASE,
    encoding="utf-8",
    echo=True
)

session = scoped_session(
    sessionmaker(
        autocommit=False,
        autoflush=False,
        bind=ENGINE
    )
)

Base = declarative_base()
Base.query = session.query_property()

model.py

from sqlalchemy import Column, Integer, String
from pydantic import BaseModel
from db import Base
from db import ENGINE

# テーブル定義
class TestUserTable(Base):
    __tablename__ = 'test_user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(30), nullable=False)
    email = Column(String(128), nullable=False)

# モデル定義 
class TestUser(BaseModel):
    id: int
    name: str
    email: str


def main():
    # テーブル構築
    Base.metadata.create_all(bind=ENGINE)


if __name__ == "__main__":
    main()

main.py

  • テストユーザーの取得、一覧取得、登録、更新API定義
from fastapi import FastAPI
from db import session
from model import TestUserTable, TestUser

app = FastAPI()

# ユーザー情報一覧取得
@app.get("/test_users")
def get_user_list():
    users = session.query(TestUserTable).all()
    return users


# ユーザー情報取得(id指定)
@app.get("/test_users/{user_id}")
def get_user(user_id: int):
    user = session.query(TestUserTable).\
        filter(TestUserTable.id == user_id).first()
    return user


# ユーザ情報登録
@app.post("/test_users")
def post_user(user: TestUser):
    db_test_user = TestUser(name=user.name,
                            email=user.email)
    session.add(db_test_user)
    session.commit()


# ユーザ情報更新
@app.put("/test_users/{user_id}")
def put_users(user: TestUser, user_id: int):
    target_user = session.query(TestUserTable).\
        filter(TestUserTable.id == user_id).first()
    target_user.name = user.name
    target_user.email = user.email
    session.commit()

動作確認

  1. コンテナ起動
docker-compose up -d --build
  1. API呼び出し

    1. http://localhost:8000/docs (Swagger API仕様ページ)にアクセス
    2. 対象APIを選択し、「Try it out」を選択

    例:ユーザー情報一覧取得

      curl -X 'GET' \
        'http://localhost:8000/test_users' \
        -H 'accept: application/json'
    
      [
        {
          "id": 1,
          "name": "tanaka taro",
          "email": "tanaka.taro@example.com"
        },
        {
          "id": 2,
          "name": "yamada hanako",
          "email": "yamada.hanako@example.com"
        }
      ]
    

参考情報

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8