Next.js, Tailwind y Prisma con Docker Postgres
Paso a paso: crear una aplicación Next.js con TypeScript, ejecutar Postgres en Docker, configurar Prisma migrate y seed, y consultar usuarios desde un componente del servidor.
Requisitos previos
Instale estas herramientas antes de seguir los pasos:
- Docker (para un contenedor local de Postgres)
- Node.js (se recomienda v16+)
- npm (viene incluido con Node)
1) Crear un proyecto Next.js
Use el inicializador oficial y responda a las preguntas. Para esta guía, se recomienda utilizar App Router y TypeScript.
npx create-next-app@latest notes-taking
# choose your options in the interactive prompt (App Router, TypeScript recommended)
cd note-taking
Para forzar el uso de TypeScript desde la primera orden:
npx create-next-app@latest note-taking — ts
2) Agregar Tailwind CSS (ya viene incluido en Next.js)
Las plantillas recientes de create-next-app ya incluyen Tailwind cuando se activa en las opciones interactivas, por lo que no es necesario instalarlo por separado en un proyecto nuevo que lo haya seleccionado.
3) Ejecutar Postgres con Docker (localmente)
Inicie Postgres en un contenedor:
docker run — name notes-postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=notes_app -p 5432:5432 -d postgres:latest
Significado de las opciones:
- docker run — crear e iniciar un contenedor
- --name notes-postgres — nombre estable para comandos posteriores
- -e POSTGRES_PASSWORD=... / -e POSTGRES_DB=... — credenciales iniciales y base de datos
- -p 5432:5432 — publicar el puerto en el host
- -d postgres:latest — ejecutar de forma separada y utilizar la imagen de Postgres
Confirme que está en ejecución:
docker ps
Filtrar por imagen:
docker ps — filter “ancestor=postgres”
listar todos los contenedores, incluidos los detenidos:
docker ps -a
Filtrar por nombre de contenedor:
docker ps — filter “name=notes-postgres”
4) Instalar Prisma y paquetes relacionados
Desde la raíz del proyecto Next.js:
npm install prisma tsx — save-dev
npm install @prisma/extension-accelerate @prisma/client
Inicializar Prisma y generar el cliente en la carpeta app para que las importaciones de App Router permanezcan locales:
npx prisma init — db — output ../app/generated/prisma
Eso crea un directorio prisma/ con schema.prisma, un archivo .env que contiene DATABASE_URL, y (con --output) un cliente generado en app/generated/prisma.
¿Prefiere la ubicación predeterminada del cliente? Inicialícelo sin una salida personalizada:
npx prisma init — db and remove — output.
5) Configurar .env (DATABASE_URL)
Dirija DATABASE_URL hacia la instancia Docker de Postgres:
DATABASE_URL=”postgresql://postgres:password@localhost:5432/notes_app?schema=public”
Cambie la contraseña y el nombre de la base de datos si eligió valores diferentes.
6) Editar prisma/schema.prisma
Utilice una pareja de modelos User/Post que coincida con el script de semilla posteriormente:
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])
}
Guarde el archivo cuando los modelos estén correctos.
7) Ejecutar la migración (crear tablas)
Aplique la primera migración para crear las tablas:
npx prisma migrate dev — name init
Prisma escribe SQL en prisma/migrations para ese cambio.
8) Sembrar la base de datos
Al sembrar se insertan filas de ejemplo para que Prisma Studio y la aplicación tengan datos de inmediato.
Cree prisma/seed.ts (ajuste la importación si la ruta de salida del cliente es diferente):
// 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
Registre el script de sembrado en package.json:
"prisma": {
"seed": "tsx prisma/seed.ts"
}
Ejécutelo:
npx prisma db seed
Esto inserta a Alice y Bob junto con sus publicaciones.
9) Abrir Prisma Studio
Inspeccione y edite las filas visualmente:
npx prisma studio
La interfaz del navegador muestra los modelos y registros.
10) Crear un envoltorio para el cliente Prisma (lib/prisma.ts)
Evite crear muchas instancias de PrismaClient durante el desarrollo utilizando un singleton global y la extensión accelerate. Cree 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;
Dirija la importación hacia la ruta del cliente que haya generado, o utilice @prisma/client si omitió --output.
11) Probar la conexión a la base de datos desde Next.js (componente del servidor)
Ejemplo app/page.tsx que carga usuarios en el servidor:
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>
);
}
Inicie el servidor de desarrollo de Next.js:
npm run dev
Abra http://localhost:3000 y confirme que se muestren los usuarios inicializados.
Lista completa de comandos
Crear proyecto
npx create-next-app@latest my-app
cd my-app
postgres 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
Editar prisma/schema.prisma
npx prisma migrate dev — name init
Crear prisma/seed.ts
Agregar la entrada prisma.seed a package.json
npx prisma db seed
npx prisma studio
npm run dev
Resolución de problemas y consejos
- No se puede conectar a Postgres: confirme el contenedor con
docker ps, luego verifique el host y puerto deDATABASE_URL. Intente usarpsqldesde el host o otro cliente con la misma URL. - Fallas en las migraciones: lea el SQL generado por Prisma en
prisma/migrationsy asegúrese de que el nombre de la base de datos coincida con el de.env. - Importación incorrecta del cliente: regenere los archivos después de cambiar
output, o cambie las importaciones a@prisma/clientsi utiliza la ubicación predeterminada. - Interfaz vacía: ejecute nuevamente la operación de inicialización de datos y confirme que Prisma Studio muestre a Alice/Bob antes de depurar el componente de la página.
Lecturas relacionadas
- Next.js Server Actions con Prisma y PostgreSQL — Conecte directamente las Server Actions a un cliente Prisma compartido y a PostgreSQL, de modo que las operaciones CRUD no requieran rutas API ni solicitudes desde el cliente.
- Configuración de Prisma 7 con Accelerate URLs — Explore prisma.config.ts, los argumentos del constructor, los protocolos accelerateURL y la configuración dual de DATABASE_URL en Prisma 7.
- Actualización de Prisma a v7 en una app Next.js con adaptadores de controlador — Uso de ESM, actualizaciones del esquema y del generador, dotenv, módulos de configuración e instanciación del cliente a través de adaptadores de controlador.