Saltar al contenido
SeedemGuía de despliegues

Despliegue

Paso 4: Configurar los archivos de despliegue

Paso 4 de 7

Para que Coolify pueda construir y ejecutar el proyecto hay que crear dos archivos nuevos en la raíz del repositorio (Dockerfile y server-node.mjs) y ajustar vite.config.ts. Haz estos cambios en la copia local que clonaste en tu computadora.

Crear el archivo Dockerfile

Crea un archivo llamado Dockerfile (sin extensión) en la raíz del proyecto con este contenido:

Dockerfile
# ─── Stage 1: Build ──────────────────────────────────────────────────────────
FROM node:23-alpine AS build
WORKDIR /app

# Public Supabase config — inlined into the client bundle by Vite at build
# time, so these must be passed as --build-arg (not read from a .env file,
# which is excluded from the build context via .dockerignore).
ARG VITE_SUPABASE_URL
ARG VITE_SUPABASE_PUBLISHABLE_KEY
ARG VITE_SUPABASE_PROJECT_ID
ENV VITE_SUPABASE_URL=$VITE_SUPABASE_URL
ENV VITE_SUPABASE_PUBLISHABLE_KEY=$VITE_SUPABASE_PUBLISHABLE_KEY
ENV VITE_SUPABASE_PROJECT_ID=$VITE_SUPABASE_PROJECT_ID

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
ENV NITRO_PRESET=node-server
RUN npm run build


# ─── Stage 2: Runtime ────────────────────────────────────────────────────────
FROM node:23-alpine AS runner
WORKDIR /app

ENV HOST=0.0.0.0
ENV PORT=3000
ENV NODE_ENV=production

# Reusa el MISMO node_modules que generó el bundle en Stage 1 — evita
# discrepancias de resolución/hoisting entre dos instalaciones separadas,
# que es lo que causaba "createCsrfMiddleware is not a function" en runtime.
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/.output ./.output

EXPOSE 3000

# El preset "node-server" de Nitro ya arranca su propio listener (usa
# HOST/PORT) y sirve los assets públicos al importarse — server-node.mjs
# también hace serve() en el mismo puerto y causa EADDRINUSE, así que se
# ejecuta el entrypoint de Nitro directamente.
CMD ["node", ".output/server/index.mjs"]

Crear el archivo server-node.mjs

Crea un archivo llamado server-node.mjs en la raíz del proyecto con este contenido:

server-node.mjs
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { serveStatic } from "@hono/node-server/serve-static";
import server from "./.output/server/index.mjs";

const port = Number(process.env.PORT) || 3000;
const hostname = process.env.HOST || "0.0.0.0";

const app = new Hono();

const env = {
  ASSETS: {
    fetch: async () => new Response("Not Found", { status: 404 }),
  },
  env: undefined,
};
env.env = env;

app.use("*", serveStatic({ root: "./.output/public" }));

app.all("*", (c) =>
  server.fetch(c.req.raw, env, { waitUntil: () => {}, passThroughOnException: () => {} }),
);

serve(
  {
    fetch: app.fetch,
    port,
    hostname,
  },
  (info) => {
    console.log(`Listening on http://${info.address}:${info.port}/`);
  },
);

Ajustar vite.config.ts

En el archivo vite.config.ts agrega la configuración de Nitro con el preset "node-server", para que el build genere un servidor Node:

vite.config.ts
import { defineConfig } from "@lovable.dev/vite-tanstack-config";

export default defineConfig({
  tanstackStart: {
    server: { entry: "server" },
  },
  nitro: {
    preset: "node-server",
  },
});

Detalles adicionales

  • Si existe el archivo public/favicon.ico, elimínalo.
  • Si en la carpeta src/assets hay archivos .json generados por Lovable (por ejemplo logo-ejemplo.png.asset.json), abre cada uno y completa el campo url con el dominio de las imágenes de los prototipos.
Explorador de archivos del proyecto mostrando el archivo favicon.ico dentro de la carpeta public
Si existe public/favicon.ico, bórralo.
Archivo .asset.json en src/assets con el campo url señalado
El campo "url" de cada .asset.json debe llevar el dominio completo de las imágenes de Lovable.

Subir los cambios al repositorio

Cuando los archivos estén listos, guarda los cambios y súbelos a GitHub desde la terminal, dentro de la carpeta del proyecto:

terminal
git status
git add .
git commit -m "Add config"
git push
Terminal mostrando los comandos git status, git add ., git commit -m "Add config" y git push ejecutados correctamente
git add . → git commit → git push deja los cambios en la rama main del repositorio.

De vuelta en Coolify, abre el menú "Actions" → "Deploy" para lanzar un despliegue manual con los archivos recién subidos.

Página de la aplicación en Coolify con el menú "Actions" desplegado mostrando Deploy, el historial de despliegues y el log de un despliegue
En Coolify: menú "Actions" → "Deploy". El historial muestra el estado y abajo puedes seguir el log del despliegue.
Historial de despliegues en Coolify mostrando un despliegue con estado Success y la aplicación corriendo, con el log del proceso completado
Cuando todo sale bien, el estado queda en Success y la aplicación aparece como "Running (healthy)".