1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Fast APIでDockerのMySQLコンテナに接続する方法

Posted at

はじめに

初めてやったときに若干接続するまでに手こずったので備忘録として書き残しておきます。
ディレクトリ構造は最終的に以下のようになります。

dbtest
├─ docker-compose.yml
├─ requirements.txt
│
└─blog
    ├─ database.py
    ├─ main.py
    ├─ models.py
    ├─ schemas.py
    ├─ settings.py
    └─ __init__.py

インストールするパッケージ

requirements.txtに以下の内容を記述。

requirements.txt
mysqlclient
sqlalchemy
uvicorn
fastapi
  • mysqlclient
    • mysqlをDBに使うときに必要
  • sqlalchemy
    • モデルとデータベースを紐づけ
  • uvicorn
    • サーバの起動に必要
  • fastapi
    • fastapiの利用に必要

以下のコマンドでインストール

pip install -r requirements.txt

接続するURL

DB接続設定で使うURLは以下のようなものになります。

# データベース作成時に設定したやつ
DB_USER = "root"
DB_PASS = "pass"
DB_NAME = "sample_db"

# 接続するホストのIPアドレス
DB_HOST = "127.0.0.1"
# 接続するポート番号
DB_PORT = "3007"

# mysql://root:pass@127.0.0.1:3007/sample_db
DATABASE_URL = f"mysql://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}"

database設定を書き込むpythonファイルの全体像は以下のようになりました。
settings.pyに接続に必要な値は分離しています。

database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from settings import DB_USER, DB_PASS, DB_NAME, DB_PORT, DB_HOST

DATABASE_URL = f"mysql://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}"

engine = create_engine(DATABASE_URL)

sessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)

Base = declarative_base()

モデルの作成

まず、schemas.pyでスキーマを定義。

schemas.py
from pydantic import BaseModel

class Blog(BaseModel):
    title: str
    body: str

次に、モデルを記述するためのファイルを作成。ここで、String型は文字列の最大長をString(16)みたいな感じで指定しないとエラーを吐かれたので注意です。

models.py
from sqlalchemy import Column, Integer, String
from database import Base

class Blog(Base):
    __tablename__ = "blogs" # テーブルの名前を明示できる

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(16))
    body = Column(String(16))

モジュールをmain.pyで統合する。

main.py
from fastapi import FastAPI, Depends
from schemas import Blog
from models import Base
from database import engine, sessionLocal
from sqlalchemy.orm import Session
import models

app = FastAPI()

#DBテーブル作成
Base.metadata.create_all(bind=engine)

def get_db():
    db = sessionLocal()

    try:
        yield db
    finally:
        db.close()

@app.post('/blog')
def create(blog: Blog, db: Session = Depends(get_db)):
    new_blog = models.Blog(title=blog.title, body=blog.body)
    db.add(new_blog)
    db.commit()
    db.refresh(new_blog)
    return new_blog

MySQLコンテナを起動

docker-compose.ymlに以下の内容を記述。

version: '3'

services:
  db:
    image: mysql:5.7
    container_name: testMysql
    ports:
      - "3307:3306"
    environment:
      MYSQL_DATABASE: sample_db
      MYSQL_ROOT_USER: root
      MYSQL_ROOT_PASSWORD: pass

docker-compose.ymlが直下にあるディレクトリに移動して、コンテナを立ち上げる。

docker-compose up -d

サーバーを起動

blogディレクトリに移動して、サーバーを立ち上げる。

uvicorn main:app --reload

mysql workbenchで確認してみると...

blogsテーブルが自動生成されていることが確認できました。

ちなみに、Dockerコンテナから直接確認するには以下のようにします。

docker exec -it testMysql /bin/bash
mysql -uroot -p
//ここでパスワード求められるので、設定したものを入力
use sample_db
SHOW TABLES; //下のような図が確認できたらOK
+---------------------+
| Tables_in_sample_db |
+---------------------+
| blogs               |
+---------------------+

データを送信してみる

サーバーを立ち上げた状態で以下のURLにアクセス。
http://localhost:8000/docs

次のようなページが開くので、「Try it out」をクリック。
スクリーンショット 2022-11-07 153322.png
適当な値を入力してexecute
スクリーンショット 2022-11-07 153537.png
mysqlコンテナで以下のクエリを実行してpostしたデータが登録されていたら成功。

SELECT * FROM blogs;

おわりに

Fast APIはかなり簡潔でわかりやすいなあと思いました。初心者の人はFast APIを最初に触ってから他のフレームワークに移動するって流れにしたら理解しやすくなるのでは?と感じています。

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?