はじめに
FastAPI を使って MySQL と連携したバックエンド API を構築する中で、Next.js などのフロントエンドとの通信時に CORS エラーや接続問題に悩まされました。
個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。
今回はそれらの課題を解決し、Docker 上でも安定稼働する構成を整備するための実装と設定を整理します。
書こうと思ったきっかけ
ITスクールでのチーム開発の中で、FastAPI と MySQL を Docker 上に載せて実行しつつ、Next.js フロントエンドから呼び出す構成を組んでいました。その際に CORS エラーや DB 接続不良に悩まされたため、次回以降スムーズに構築できるよう備忘録として記録しています。
実装の目的とポイント
- FastAPI + MySQL を組み合わせたAPI構築
- CORS対応 により、Next.js など外部フロントエンドからのアクセス許可
- 接続リソースの安定性(コネクションクローズなど)
Next.js フロントエンドの修正
Next.js 側の src/app/page.tsx
を以下のように修正することで、FastAPI の /
エンドポイントからメッセージを取得し、画面上に表示できるようにしました。
"use client";
import { useEffect, useState } from "react";
import Image from "next/image";
export default function Home() {
const [message, setMessage] = useState("Loading...");
useEffect(() => {
fetch("http://localhost:8000/") // FastAPI の URL に合わせて変更
.then((res) => res.json())
.then((data) => setMessage(data.message))
.catch(() => setMessage("Error fetching message from FastAPI."));
}, []);
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
{/* 🔽 FastAPI のメッセージ表示部分 🔽 */}
<div className="text-lg text-center sm:text-left font-bold text-blue-600">
{message}
</div>
<ol className="list-inside list-decimal text-sm/6 text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
<li className="mb-2 tracking-[-.01em]">
You are now connected to FastAPI backend!
</li>
<li className="tracking-[-.01em]">
Edit <code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">src/app/page.tsx</code> to customize.
</li>
</ol>
<div className="flex gap-4 items-center flex-col sm:flex-row">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
href="https://vercel.com/new"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
href="https://nextjs.org/docs"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
</div>
</main>
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org →
</a>
</footer>
</div>
);
}
FastAPI バックエンドの修正
修正前のコード問題点
- CORSの設定がないため、外部フロントからブロックされる
- DB接続が close されておらず、リソースリークの懸念
修正済みの main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import mysql.connector
import os
app = FastAPI()
# ✅ CORS設定(Next.jsからアクセス可能にする)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 必要なら "http://localhost:3000" などに限定
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"message": "Hello from FastAPI + MySQL in Docker!"}
@app.get("/db-status")
def db_status():
try:
connection = mysql.connector.connect(
host="db", # ← Dockerコンテナ名
user=os.getenv("MYSQL_USER"),
password=os.getenv("MYSQL_PASSWORD"),
database=os.getenv("MYSQL_DATABASE")
)
if connection.is_connected():
connection.close() # ✅ 接続が確認できたら明示的にクローズ
return {"db_status": "connected"}
else:
return {"db_status": "not connected"}
except Exception as e:
return {"db_status": "error", "details": str(e)}
環境変数 .env
MYSQL_ROOT_PASSWORD=rootpassword
MYSQL_DATABASE=fastapi_db
MYSQL_USER=fastapi_user
MYSQL_PASSWORD=fastapi_pass
動作確認
API起動コマンド:
uvicorn main:app --host 0.0.0.0 --port 8000
エンドポイント:
http://localhost:8000/
http://localhost:8000/db-status
まとめ
この構成は、学習用でも実践でも役立つ FastAPI + MySQL + Docker の最小連携パターンです。
CORS や DB の扱いに注意すれば、フロントエンドともシームレスに連携できます。
今後はこれをベースに docker-compose 化やセキュリティ面の最適化にも取り組んでいきたいと思います!