1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

スクールのハッカソンに向けて環境構築したときの備忘録です。

構成

フロント用とバックエンドでリポジトリを分けました。
フロントは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
# 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
# docker-compose.yml
version: '3.8'
services:
  next-app:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - CHOKIDAR_USEPOLLING=true # ホットリロード
ファイル作成:.dockerignore
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

対応
一旦作成したファイルを一掃したあと下記のコマンドを実行

ローカルにNext.jsプロジェクトを作成
npx create-next-app@latest next-app
cd next-app

もしUnexpected token '??=' のエラーが出た場合
Node.js のバージョンを新しくしてください

nvm をインストール(初めてなら)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

nvmの読み込み(または .bashrc / .zshrc に追記)
export NVM_DIR="$HOME/.nvm"
source "$NVM_DIR/nvm.sh"
Node.js の新しいバージョンをインストール(例:v22.7.0)
nvm install 22.7.0
再度Next.jsプロジェクトを作成
npx create-next-app@latest next-app

もう一度、Dockerifleとdocker-compose.ymlファイルを作成

コンテナをビルドして起動
docker compose up --build

ブラウザで[http://localhost:3000]にアクセス

ついでにMakefile(コマンドマイ辞書みたいなやつ)も作る

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 の開発環境

requirements.txt
fastapi
uvicorn[standard]
mysql-connector-python
.env
MYSQL_ROOT_PASSWORD=ルートパスワード
MYSQL_DATABASE=データベース名
MYSQL_USER=DBユーザー名
MYSQL_PASSWORD=DBログインパスワード
main.py
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)}
Dockerfile
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"]
docker-compose.yml
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

Next.jsとFastAPIの接続

frontend/src/app/page.tsx
"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>
    </>
  );
}

backend/app/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("/")
~~

image.png

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?