0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ハッカソン開発記#9】# Next.js + FastAPI + SeleniumをVercelとRenderにデプロイしたときのエラーと解決策

0
Posted at

Next.js + FastAPI + SeleniumをVercelとRenderにデプロイしたときのエラーと解決策

ハッカソンに向けて、「会場名からライブ情報を検索するアプリ」を開発した。
フロントエンドに Next.js (Vercel)、バックエンドに FastAPI (Render) を採用し、スクレイピングに Selenium を使用した。

ローカルでは完璧に動いていたが、本番環境へのデプロイ過程でエラーが出たため、自分用として解決策をまとめる。

1. バックエンド(Render)

①:pip freeze で requirements.txt が大爆発

仮想環境で pip freeze > requirements.txt を実行したところ、関連パッケージまで全て書き出され、Renderでのビルドエラーの温床になった。(Ubuntuの設定やらなにやら)

【解決策】
クラウド環境では依存関係を自動解決してくれるため、直接インストールした主要パッケージのみを手動で記述するシンプルな形に修正した。

②:Renderの標準環境ではSelenium(Chrome)が動かない

ローカルと同じ感覚でRenderにデプロイすると、実行時に「Chromeが見つからない」というWebDriverエラーで500エラーが連発した。Renderの標準Python環境にはChrome本体がインストールされていないのが原因だった。

【解決策】
環境(Runtime)を Docker に変更し、Chromeとドライバーをインストールする Dockerfile を自作した(AIが)。

# Dockerfile
FROM python:3.10-slim

RUN apt-get update && apt-get install -y \
    chromium \
    chromium-driver \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

CMD ["uvicorn", "Main:app", "--host", "0.0.0.0", "--port", "10000"]

③:環境変数名の不一致による沈黙

フロントエンドと通信できたにもかかわらず500エラーが発生。Renderのログを確認すると、Python側で os.getenv("GEMINI_API_KEY") と呼び出しているのに、Renderの環境変数設定では ApiKey という名前で登録していたため、キーが見つからずクラッシュしていた。
「エラーが起きたら何よりもまずRenderのログを見る」

2. データベース(Vercel)

④:VercelでのインメモリDBリセット

ログイン機能を実装する際、最初はローカルのメモリ内(配列)にユーザー情報を保存する構成にしていた。しかし、Vercelは「サーバーレス」であるため、リクエストが完了するたびにサーバーが初期化され、登録したユーザーデータが即座に消滅してしまった。

【解決策】
Vercelが公式に提供している無料の Vercel Postgres に移行。ダッシュボードからDBを作成し、@vercel/postgres パッケージを導入して本物のデータベースへSQLで書き込むように修正した。

// 修正後:Postgresへの書き込み
import { sql } from "@vercel/postgres";

// 新規登録処理の一部
await sql`
  INSERT INTO users (email, passwordHash)
  VALUES (${email}, ${hashedPassword})
`;

3. フロントエンド(Next.js)

⑤:接続先が localhost のまま(通信拒否)

バックエンドをRenderにデプロイし、FastAPI側のCORS設定でフロントエンドのURLを許可した。しかし、画面からリクエストを送ると ERR_CONNECTION_REFUSED が発生。
原因は、フロントエンドの api.ts の向き先URLが http://localhost:8000 のままだったことだ。

【解決策】
向き先を Render の本番URLに変更した。

⑥:タグ削除によるGridレイアウトの崩壊

UIのブラッシュアップ中、不要な画面遷移を防ぐために タグを削除したところ、画面のレイアウトが盛大に崩壊した。
原因は、親要素の grid-cols-3 の直下に単一のブロックが存在しなくなったことで、中の要素(画像、タイトル、テキスト)がバラバラに独立したセルとして扱われてしまったためだ。

【解決策】
外した <Link> タグの代わりに <div> タグで全体を囲み直すことで、1つのブロックとして認識させ、レイアウトを修復した。

⑦:初期表示の遅延(不要なAPIフェッチ)

検索ページを開いた際、会場リストを取得するためのAPI通信を行っていたため、画面の表示にタイムラグが生じていた。

【解決策】
現段階では「マリンメッセ福岡」しかスクレイピングの対応ができていないため、useEffect での通信をまるごと削除し、初期値としてハードコーディングすることで画面表示速度を速めた(ここは今後の展望)

// 修正前:通信して待機
// const [venues, setVenues] = useState<string[]>([]);
// useEffect(() => { fetchVenues().then(setVenues) }, []);

// 修正後:ハードコーディングで即時表示
const [venues, setVenues] = useState<string[]>(["マリンメッセ福岡"]);
const [selectedVenue, setSelectedVenue] = useState<string | null>("マリンメッセ福岡");

まとめ

  • サーバーレス(Vercelなど)ではファイルの書き込みやメモリ保存はできない。DBを用意する

  • RenderでSeleniumを動かすならDocker化&ヘッドレス設定が必須

  • 謎のエラーが出たら、まずはバックエンドのログを見る

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?