Inicio / Artículos / Next.js, Tailwind y Prisma con Docker Postgres

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.

1108 palabras

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 de DATABASE_URL. Intente usar psql desde el host o otro cliente con la misma URL.
  • Fallas en las migraciones: lea el SQL generado por Prisma en prisma/migrations y 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/client si 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