はじめに
スクールのハッカソンに向けて環境構築したときの備忘録です。
構成
フロント用とバックエンドでリポジトリを分けました。
フロントはNext.js,バックエンドはFastAPIを使います。
完成形はこちら
frontend/
├── docker-compose.yml # Docker設定(開発環境)
├── Dockerfile # アプリ用Dockerイメージ定義
├── eslint.config.mjs # ESLint 設定
├── Makefile # よく使うコマンドの簡略化
├── next.config.ts # Next.js 設定
├── package.json # 依存ライブラリ定義
├── postcss.config.mjs # Tailwind CSS等のPostCSS設定
├── public/ # 公開アセット(画像等)
│ ├── *.svg
├── README.md # プロジェクト概要(このファイル)
├── src/
│ └── app/
│ ├── favicon.ico # ブラウザアイコン
│ ├── globals.css # 全体スタイル
│ ├── layout.tsx # レイアウトコンポーネント
│ └── page.tsx # トップページ
└── tsconfig.json # TypeScript 設定
backend/
├── app
│ ├── __pycache__ # Python のキャッシュファイル(無視可)
│ ├── main.py # アプリケーションのメインスクリプト
│ └── requirements.txt # Python の依存ライブラリ定義
├── docker-compose.yml # Docker Compose 設定ファイル
├── Dockerfile # Docker イメージビルド定義
└── Makefile # 開発用コマンドまとめ
Next.js + Tailwind CSS の開発環境構築
npxを実行するためNode.jsのインストールが必要です。
公式サイトからLTS(推奨版)をダウンロードし、インストールしてください。
インストールしたら下記コマンドでバージョンが表示されるか確認します
node -v
npm -v
準備が整ったらlet's環境構築です
mkdir frontend
cd frontend
# Dockerfile
FROM node:18-alpine
# 作業ディレクトリを作成
WORKDIR /app
# 依存ファイルを先にコピーしてインストール
COPY package.json package-lock.json ./
RUN npm install
# 残りのファイルをコピー
COPY . .
# Next.js のデフォルトポートを開放
EXPOSE 3000
# devサーバー起動(ホットリロード対応)
CMD ["npm", "run", "dev"]
# docker-compose.yml
version: '3.8'
services:
next-app:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- CHOKIDAR_USEPOLLING=true # ホットリロード
node_modules
npm-debug.log
docker compose run --rm nextjs npx create-next-app@latest . --typescript
コマンドの意味
Docker Compose の nextjs サービスを使って、
npx create-next-app@latest . --typescript を実行し、現在のディレクトリに TypeScript対応の Next.js アプリ が作る。
実行後は使ったコンテナが消える(--rm のおかげ)。
「Dockerfileに[COPY package.json package-lock.json ./]があるのにコピー元のpackage.jsonがないよ」とエラー出ました
ERROR [nextjs 3/5] COPY package.json package-lock.json 0.0s
[nextjs 3/5] COPY package.json package-lock.json ./:
failed to solve: failed to compute cache key: failed to calculate checksum of ref n006mml8u3hi4nnbxtk19mjga::mphnroaykwtth4rgglf02sv66: "/package.json": not found
対応
一旦作成したファイルを一掃したあと下記のコマンドを実行
npx create-next-app@latest next-app
cd next-app
もしUnexpected token '??=' のエラーが出た場合
Node.js のバージョンを新しくしてください
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
export NVM_DIR="$HOME/.nvm"
source "$NVM_DIR/nvm.sh"
nvm install 22.7.0
npx create-next-app@latest next-app
もう一度、Dockerifleとdocker-compose.ymlファイルを作成
docker compose up --build
ブラウザで[http://localhost:3000]にアクセス
ついでにMakefile(コマンドマイ辞書みたいなやつ)も作る
up:
docker compose up --build
up-d:
docker compose up -d
ps:
docker compose ps
logs:
docker compose logs
exec:
docker compose exec -it next-app bash
down:
docker compose down
FastAPI + MySQL の開発環境
fastapi
uvicorn[standard]
mysql-connector-python
MYSQL_ROOT_PASSWORD=ルートパスワード
MYSQL_DATABASE=データベース名
MYSQL_USER=DBユーザー名
MYSQL_PASSWORD=DBログインパスワード
from fastapi import FastAPI
import mysql.connector
import os
app = FastAPI()
@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", # コンテナ名
user=os.getenv("MYSQL_USER"),
password=os.getenv("MYSQL_PASSWORD"),
database=os.getenv("MYSQL_DATABASE")
)
if connection.is_connected():
return {"db_status": "connected"}
except Exception as e:
return {"db_status": "error", "details": str(e)}
FROM python:3.11-slim
WORKDIR /app
COPY app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app/ .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
version: '3.8'
services:
web:
build: .
container_name: fastapi-app
ports:
- "8000:8000"
volumes:
- ./app:/app
env_file:
- .env
depends_on:
- db
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
db:
image: mysql:8.0
container_name: mysql-db
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
ports:
- "3306:3306"
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
docker compose up --build
-
アプリ:
http://localhost:8000/ → {"message": "Hello from FastAPI + MySQL in Docker!"} -
DB接続確認:
http://localhost:8000/db-status → {"db_status": "connected"}(成功時)
Next.jsと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 (
<>
{/* 🔽 FastAPI のメッセージ表示部分 🔽 */}
<div className="text-lg text-center sm:text-left font-bold text-blue-600">
{message}
</div>
</>
);
}
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("/")
~略~