Next.js、Tailwind 与 Prisma,结合 Docker 和 PostgreSQL 使用
逐步操作:创建一个 Next.js TypeScript 应用,在 Docker 中运行 Postgres,配置 Prisma migrate 及数据初始化,然后从服务器组件中查询用户信息。
前置条件
在开始操作之前,请先安装以下工具:
- Docker(用于本地 Postgres 容器)
- Node.js(建议使用 v16+ 版本)
- npm(随 Node 一同提供)
1) 创建 Next.js 项目
使用官方初始化工具并回答提示问题。本教程建议使用 App Router 和 TypeScript。
npx create-next-app@latest notes-taking
# choose your options in the interactive prompt (App Router, TypeScript recommended)
cd note-taking
若想从第一个命令就开始使用 TypeScript:
npx create-next-app@latest note-taking — ts
2) 添加 Tailwind CSS(Next.js 已内置)
最新的 create-next-app 模板在交互式选项中启用 Tailwind 后会自动集成该框架,因此对于已选择该功能的新建项目无需单独安装 Tailwind。
3) 使用 Docker(在本地)运行 Postgres
在容器中启动 Postgres:
docker run — name notes-postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=notes_app -p 5432:5432 -d postgres:latest
各参数的含义:
- docker run — 创建并启动容器
- --name notes-postgres — 为后续命令提供稳定的名称
- -e POSTGRES_PASSWORD=... / -e POSTGRES_DB=... — 设置启动凭据及数据库信息
- -p 5432:5432 — 将端口映射到主机上
- -d postgres:latest — 以分离模式使用 Postgres 镜像
确认容器正在运行:
docker ps
按镜像过滤:
docker ps — filter “ancestor=postgres”
列出所有容器,包括已停止的:
docker ps -a
按容器名称过滤:
docker ps — filter “name=notes-postgres”
4) 安装 Prisma 及相关包
在 Next.js 项目根目录下:
npm install prisma tsx — save-dev
npm install @prisma/extension-accelerate @prisma/client
初始化 Prisma,并在 app 文件夹下生成客户端代码,以便 App Router 的导入操作仍在本地完成:
npx prisma init — db — output ../app/generated/prisma
这样就会生成一个包含schema.prisma文件的prisma/目录,一个包含DATABASE_URL值的.env文件,以及(使用--output参数时)在app/generated/prisma下生成的客户端代码。
更希望使用默认的客户端存放位置?那就无需指定自定义输出路径直接进行初始化:
npx prisma init — db and remove — output.
5) 配置.env文件(DATABASE_URL)
将DATABASE_URL设置为Docker中的Postgres实例地址:
DATABASE_URL=”postgresql://postgres:password@localhost:5432/notes_app?schema=public”
如果选择了不同的密码和数据库名称,则需相应修改这些值。
6) 编辑prisma/schema.prisma文件
需使用与后续种子脚本相匹配的User/Post模型对:
generator client {
provider = "prisma-client-js"
output = "../app/generated/prisma"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
}
当模型内容正确无误后保存该文件。
7) 运行迁移操作(创建表结构)
执行第一个迁移命令以创建数据库表:
npx prisma migrate dev — name init
Prisma会在prisma/migrations目录下生成用于该变更的SQL语句。
8) 初始化数据库
初始化操作会插入示例数据,这样Prisma Studio和应用程序就能立即拥有数据。
创建prisma/seed.ts文件(如果客户端输出路径不同,请调整导入语句):
// prisma/seed.ts
import { PrismaClient, Prisma } from "../app/generated/prisma";
const prisma = new PrismaClient();
const userData: Prisma.UserCreateInput[] = [
{
name: "Alice",
email: "alice@prisma.io",
posts: {
create: [
{
title: "Join the Prisma Discord",
content: "https://pris.ly/discord",
published: true,
},
{
title: "Prisma on YouTube",
content: "https://pris.ly/youtube",
},
],
},
},
{
name: "Bob",
email: "bob@prisma.io",
posts: {
create: [
{
title: "Follow Prisma on Twitter",
content: "https://www.twitter.com/prisma",
published: true,
},
],
},
},
];
export async function main() {
for (const u of userData) {
await prisma.user.create({ data: u });
}
}
main();ty
在package.json中注册该初始化脚本:
"prisma": {
"seed": "tsx prisma/seed.ts"
}
运行该脚本:
npx prisma db seed
这样就会插入Alice、Bob以及他们的帖子。
9) 打开Prisma Studio
可以直观地查看和编辑数据行:
npx prisma studio
浏览器界面会列出模型和记录。
10) 创建Prisma客户端封装文件(lib/prisma.ts)
通过使用全局单例以及accelerate扩展,可以避免在开发过程中创建过多的PrismaClient实例。请创建lib/prisma.ts文件:
// lib/prisma.ts
import { PrismaClient } from "../app/generated/prisma"; // adjust path if needed
import { withAccelerate } from "@prisma/extension-accelerate";
declare global {
// allow global prisma across module reloads in dev
// eslint-disable-next-line no-var
var prisma: PrismaClient | undefined;
}
const prisma =
global.prisma ?? new PrismaClient().$extends(withAccelerate());
if (process.env.NODE_ENV !== "production") global.prisma = prisma;
export default prisma;
将导入路径设置为您生成的客户端路径,如果您省略了--output选项,则使用@prisma/client。
11) 从 Next.js(服务器组件)测试数据库连接
一个在服务器端加载用户的示例app/page.tsx:
import prisma from '@/lib/db'
export default async function Home() {
const users = await prisma.user.findMany();
return (
<div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16">
<h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)] text-[#333333]">
Superblog
</h1>
<ol className="list-decimal list-inside font-[family-name:var(--font-geist-sans)]">
{users.map((user) => (
<li key={user.id} className="mb-2">
{user.name}
</li>
))}
</ol>
</div>
);
}
启动 Next.js 开发服务器:
npm run dev
打开 http://localhost:3000,确认已生成的测试用户能够正确显示。
完整命令清单
创建项目
npx create-next-app@latest my-app
cd my-app
使用 PostgreSQL Docker
docker run — name notes-postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=notes_app -p 5432:5432 -d postgres:latest
执行 docker ps 命令
docker exec -it notes-postgres psql -U postgres
使用 Prisma 工具
npm install prisma tsx — save-dev
npm install @prisma/extension-accelerate @prisma/client
npx prisma init — db — output ../app/generated/prisma
编辑 prisma/schema.prisma 文件
npx prisma migrate dev — name init
创建 prisma/seed.ts 文件
在 package.json 中添加 prisma.seed 条目
npx prisma db seed
npx prisma studio
npm run dev
故障排除与技巧
- 无法连接到 Postgres:使用
docker ps确认容器状态,然后检查DATABASE_URL中的主机地址和端口。可从主机或其他客户端使用psql命令连接该地址。 - 迁移失败:查看
prisma/migrations目录下生成的 SQL 文件,确保数据库名称与.env文件中的配置一致。 - 客户端导入错误:修改
output设置后需重新生成代码,若使用默认路径则应将导入方式改为@prisma/client。 - 界面为空:在调试页面组件之前,先重新运行数据初始化脚本,并确认 Prisma Studio 中显示了 Alice/Bob 的信息。