DockerでFastAPI+Next.js+MySQLの環境を構築してみる(Windows)
アプリケーションの定義ファイル(YAML)作成
type nul > docker-compose.yml下記の内容で編集。
services:
backend:
build: ./infra/fastapi
command: sh -c "python3 -m debugpy --listen 0.0.0.0:5678 -m uvicorn main:app --reload --proxy-headers --host='0.0.0.0' --port=8000"
ports:
- "8000:8000"
- "5678:5678"
volumes:
- ./backend:/app
frontend:
build: ./infra/nextjs
tty: true
volumes:
- ./frontend:/app
environment:
- WATCHPACK_POLLING=true
command: sh -c "npm run dev"
ports:
- "3000:3000"
db:
build: ./infra/mysql
volumes:
- db-store:/var/lib/mysql
ports:
- "3306:3306"
volumes:
db-store:
backendコンテナ(FastAPI)作成
Dockerファイル作成
ディレクトリ作成。
mkdir -p infra/fastapiDockerファイル作成。
type nul > infra/fastapi/Dockerfile下記の内容で編集。
# ベースイメージを指定
FROM python:3.9
# 作業ディレクトリを作成
WORKDIR /app
# 必要なパッケージをインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションのソースコードをコピー
COPY . .
# アプリケーションを起動
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
requirements.txt作成
type nul > infra/fastapi/requirements.txtuvicorn
fastapi
mysqlclient
sqlalchemy
debugpy
frontendコンテナ(Next.js)作成
Dockerファイル作成
ディレクトリ作成。
mkdir infra/nextjsファイル作成。
type nul > infra/nextjs/Dockerfile下記の内容で編集。
FROM node:24.15.0
WORKDIR /app
DBコンテナ(MySQL)作成
Dockerファイル作成
ディレクトリ作成。
mkdir infra/mysqlファイル作成。
type nul > infra/mysql/Dockerfile下記の内容で編集。
FROM mysql/mysql-server:8.0
ENV MYSQL_DATABASE=odaneko \
MYSQL_USER=odaneko \
MYSQL_PASSWORD=odaneko \
MYSQL_ROOT_PASSWORD=odaneko \
TZ=Asia/Tokyo
COPY ./my.cnf /etc/my.cnf
RUN chmod 644 /etc/my.cnf
confファイル作成
type nul > infra/mysql/my.cnf下記の内容で編集。
[mysqld]
# default
skip-host-cache
skip-name-resolve
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
secure-file-priv = /var/lib/mysql-files
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
# character set / collation
character_set_server = utf8mb4
collation_server = utf8mb4_ja_0900_as_cs_ks
# timezone
default-time-zone = SYSTEM
log_timestamps = SYSTEM
# Error Log
log-error = mysql-error.log
# Slow Query Log
slow_query_log = 1
slow_query_log_file = mysql-slow.log
long_query_time = 1.0
log_queries_not_using_indexes = 0
# General Log
general_log = 1
general_log_file = mysql-general.log
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
API作成
backendディレクトリ作成
mkdir backend環境変数作成
type nul > backend/.envDB_HOST=db:3306
DB_NAME=odaneko
DB_USER=odaneko
DB_PASSWORD=odaneko
db.py作成
MySQL接続用のコードを作成。
type nul > backend/db.pyimport os
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session
host = "db:3306"
db_name = "odaneko"
user = "odaneko"
password = "odaneko"
DATABASE = 'mysql://%s:%s@%s/%s?charset=utf8' % (
user,
password,
host,
db_name,
)
ENGINE = create_engine(
DATABASE,
echo=True
)
session = scoped_session(
sessionmaker(
autocommit=False,
autoflush=False,
bind=ENGINE
)
)
Base = declarative_base()
Base.query = session.query_property()
main.pyを作成
APIの処理が記載されたプログラムを作成。
type nul > backend/main.py下記の内容で編集。
DB接続確認を行うAPIです。
from fastapi import FastAPI
from db import session
from sqlalchemy import text
app = FastAPI()
@app.get("/db-test")
def mysql_test():
query = text("SELECT 1;")
result = session.execute(query).scalar()
return {
"result": result
}
フロントページ作成
アプリ作成
docker compose run --rm frontend sh -c 'npx create-next-app . --typescript'

環境変数作成
type nul > frontend/.envBACKEND_API_URL=http://backend:8000
ページ作成
mkdir frontend/app/db-testtype nul > frontend/app/db-test/page.tsx"use client";
import { useEffect, useState } from "react";
export default function Home() {
const [result, setResult] = useState<number | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
useEffect(() => {
const executeTest = async () => {
try {
const response = await fetch("/api/db-test");
if (!response.ok) {
throw new Error("API request failed");
}
const data = await response.json();
setResult(data.result);
} catch (error) {
setError("APIの呼び出しに失敗しました");
} finally {
setLoading(false);
}
};
executeTest();
}, []);
return (
<main>
<h1>Python API 接続テスト</h1>
{loading && <p>読み込み中...</p>}
{result !== null && (
<p>
DB検索結果:{result}
</p>
)}
{error && (
<p>
エラー:{error}
</p>
)}
</main>
);
}
API作成
mkdir frontend/app/api/db-testtype nul > frontend/app/api/db-test/route.tsimport { NextResponse } from "next/server";
export async function GET() {
const response = await fetch(
`${process.env.BACKEND_API_URL}/db-test`
);
const data = await response.json();
return NextResponse.json(data);
}
コンテナビルド・起動
docker compose up -d --build
Dockerデスクトップでも起動を確認。

環境が構築できたか確認
下記のURLを開いて、テストページが表示されるか確認。
http://localhost:3000/db-test

以上になります。
お読み頂き、ありがとうございました。

