Next.js + PostgreSQL + Dockerで開発環境を作る【Art Navi開発記録 #3】
はじめに
こんにちは。
なかのひとカンパニーの archer です。
美術展検索サービス Art Navi の開発内容を、備忘録も兼ねて記事にしています。
- サービスURL: https://art-weekend.jp/
前回は、LocalStorageを使ったお気に入り機能について書きました。
今回は、Art Navi の開発環境として使っている Next.js + PostgreSQL + Docker の構成についてまとめます。
今回の目的
Art Navi では、フロントエンドとバックエンドを Next.js で作り、データベースには PostgreSQL を使っています。
開発環境では、PostgreSQL をローカルに直接インストールせず、Docker Compose で起動する方針にしました。
理由は以下です。
- 環境構築を再現しやすくしたい
- DBをローカルPCに直接入れたくない
- 本番環境に近い形で開発したい
- 他のサービス開発にも流用しやすくしたい
技術構成
今回の構成は以下です。
Next.js App Router
PostgreSQL
Docker
Docker Compose
開発時のイメージは以下です。
ブラウザ
↓
Next.js
↓
PostgreSQL
PostgreSQL は Docker コンテナとして起動します。
Next.js はローカルで pnpm dev してもよいですし、必要に応じて Docker コンテナ化することもできます。
ディレクトリ構成
ざっくりした構成は以下です。
art-navi/
app/
components/
lib/
db/
public/
Dockerfile
docker-compose.yml
package.json
.env.local
主に使うのは以下です。
app/
Next.js App Router のページ
components/
UIコンポーネント
lib/
DB接続や共通処理
db/
SQLやseedデータ
docker-compose.yml
PostgreSQLなどのコンテナ定義
.env.local
開発用の環境変数
docker-compose.yml
開発用の PostgreSQL は、Docker Compose で起動します。
例としては以下のような構成です。
services:
db:
image: postgres:16
container_name: art-navi-db
environment:
POSTGRES_USER: artnavi
POSTGRES_PASSWORD: password
POSTGRES_DB: artnavi
ports:
- "5432:5432"
volumes:
- art-navi-db-data:/var/lib/postgresql/data
volumes:
art-navi-db-data:
これで、PostgreSQL をコンテナとして起動できます。
docker compose up -d
DBコンテナが起動しているか確認します。
docker compose ps
環境変数
Next.js から PostgreSQL に接続するため、.env.local に接続情報を書きます。
DATABASE_URL="postgresql://artnavi:password@localhost:5432/artnavi"
Docker上のDBをローカルのNext.jsから使う場合は、localhost:5432 で接続できます。
本番環境では接続先が変わるため、.env.local と .env.production は分けて管理します。
DB接続処理
DB接続処理は lib/db.ts のようなファイルにまとめます。
import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
export async function query<T>(text: string, params?: unknown[]) {
const result = await pool.query<T>(text, params);
return result;
}
DB接続処理を1か所にまとめておくと、ページやAPI側から使いやすくなります。
Route HandlerからDBを使う
Next.js App Router では、Route Handler を使ってAPIを作れます。
たとえば、展覧会一覧を返すAPIは以下のようなイメージです。
app/
api/
exhibitions/
route.ts
import { NextResponse } from "next/server";
import { query } from "@/lib/db";
export async function GET() {
const result = await query(
"select id, title, venue_name, starts_at, ends_at from exhibitions order by starts_at desc"
);
return NextResponse.json(result.rows);
}
これで、/api/exhibitions にアクセスすると、DBから取得した展覧会データをJSONで返せます。
テーブル作成
MVP段階では、まず展覧会情報を保存するテーブルを用意します。
例としては以下のようなイメージです。
create table exhibitions (
id serial primary key,
title text not null,
venue_name text not null,
area_name text not null,
genre_name text not null,
starts_at date not null,
ends_at date not null,
description text not null,
created_at timestamp not null default current_timestamp
);
最初から完璧な正規化を目指すより、MVPでは画面に必要な情報を出せることを優先しました。
あとから以下のように分けることもできます。
venues
areas
genres
exhibitions
まずは小さく作って、必要になったら整理する方針です。
seedデータ
開発中は、動作確認用のデータが必要になります。
そのため、seed用のSQLを用意しておきます。
insert into exhibitions (
title,
venue_name,
area_name,
genre_name,
starts_at,
ends_at,
description
) values
(
'印象派と光の表現',
'上野の美術館',
'上野',
'西洋美術',
'2026-06-01',
'2026-08-31',
'印象派の作品を中心に、光の表現に注目した展覧会です。'
),
(
'現代アートの現在地',
'六本木の美術館',
'六本木',
'現代アート',
'2026-07-01',
'2026-09-15',
'国内外の現代アート作品を紹介する展覧会です。'
);
サンプルデータがあると、一覧画面や詳細画面の確認がしやすくなります。
開発時の起動手順
開発時は、まずDBを起動します。
docker compose up -d
次に、Next.jsを起動します。
pnpm dev
ブラウザで確認します。
http://localhost:3000
DBコンテナを止める場合は以下です。
docker compose down
データも含めて削除したい場合は、volumeも削除します。
docker compose down -v
ただし、-v を付けるとDBデータも消えるため注意が必要です。
Dockerを使ってよかった点
Docker Compose を使うことで、DB環境の作り直しが簡単になりました。
特によかった点は以下です。
- PostgreSQLをローカルPCに直接入れなくてよい
- DBの作成・削除が簡単
- 本番に近い構成で試せる
- 他の開発環境でも再現しやすい
- サービスごとにDBを分けやすい
個人開発でも、Dockerを使っておくと後から本番環境へ持っていきやすいと感じました。
気をつけたこと
一方で、以下は気をつける必要があります。
-
.env.localをGitに含めない - DBパスワードを公開しない
- 本番用と開発用の環境変数を分ける
-
docker compose down -vでデータを消さないようにする - PostgreSQLのポート競合に注意する
特に .env.local や .env.production は、誤ってGitHubにpushしないように .gitignore に入れています。
.env.local
.env.production
まとめ
今回は、Art Navi の開発環境として使っている Next.js + PostgreSQL + Docker の構成についてまとめました。
今回のポイントは以下です。
- PostgreSQLはDocker Composeで起動する
- Next.jsから環境変数経由でDBに接続する
- DB接続処理は
lib/db.tsにまとめる - Route HandlerからDBを参照する
-
.env系のファイルはGit管理しない
MVP段階では、まず動く状態を作ることを優先しています。
次回は、Docker ComposeでNext.jsを本番起動する構成について書く予定です。