¿Qué necesita la API antes de desplegarla?
Tres cosas. Primero, escuchar en el puerto de la variable de entorno PORT: la define Codara (8080 salvo que elijas otro puerto para la app). Segundo, un script start en package.json; Railpack lo ejecuta o, si no existe, usa el campo main o un index.js en la raíz. Tercero, una ruta de salud ligera que devuelva 200 sin tocar la base de datos.
Railpack elige npm, pnpm, Yarn o Bun según tu lockfile, ejecuta tu script build si existe (por ejemplo, tsc) y define NODE_ENV=production. Fija la versión de Node con engines.node en package.json.
import express from "express";
const app = express();
app.use(express.json());
app.get("/health", (req, res) => res.sendStatus(200));
app.get("/api/hello", (req, res) => res.json({ hello: "world" }));
const port = Number(process.env.PORT) || 8080;
const server = app.listen(port, () => console.log(`Listening on ${port}`));
// Codara detiene los contenedores antiguos con SIGTERM al publicar una versión.
process.on("SIGTERM", () => server.close(() => process.exit(0)));{
"type": "module",
"scripts": { "start": "node server.js" },
"engines": { "node": "22.x" },
"dependencies": { "express": "^5.1.0" }
}¿Cómo creas la app?
Instala la GitHub App de Codara en la cuenta propietaria del repositorio, crea un proyecto y abre Apps → New app en la consola. Elige el proyecto y el entorno, selecciona GitHub repository y la rama, y envía: el asistente crea la app y lanza su primer build. A partir de ahí, cada push a la rama despliega.
Define /health como ruta del health check en los ajustes de la app. Así Codara espera a que los contenedores nuevos respondan antes de enviarles tráfico, y una versión que nunca llega a estar sana se marca como fallida mientras la anterior sigue sirviendo.
codaracloud apps create api --client my-workspace --project shop \
--repo acme/shop-api --branch main
codaracloud deploy api --client my-workspace --project shop --source
codaracloud logs api --follow¿Cómo conectas Postgres y ejecutas las migraciones?
Crea una base de datos Postgres en el mismo entorno y conéctala a la app. Codara inyecta DATABASE_URL para las consultas y DATABASE_DIRECT_URL, que evita cualquier pooler, para las migraciones, y reinicia la app para que las lea.
Ejecuta las migraciones como comando previo al despliegue de la app, por ejemplo npx prisma migrate deploy o npm run migrate. Se ejecuta una vez en la imagen nueva antes de mover el tráfico; si falla, la versión se descarta y la actual sigue sirviendo.
import pg from "pg";
export const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });¿Puede la API ser privada o funcionar junto a un worker?
Sí. Una API a la que solo llaman tus otros servicios puede crearse como servicio interno, sin dirección pública (codaracloud apps create … --private). Su URL interna aparece como CODARA_PRIVATE_URL en Provided by Codara, y los demás servicios del mismo entorno la llaman ahí.
Un worker de colas o cualquier otro proceso de larga duración es un servicio aparte en el mismo entorno, con su propio comando de arranque, que comparte la conexión a la base de datos. El trabajo que se ejecuta según un horario va en un job de Codara con una expresión cron.
¿Cuándo conviene tu propio Dockerfile?
Cuando necesitas paquetes del sistema que Railpack no instala, una imagen base concreta o un build que ya usas en otro sitio. Un archivo llamado exactamente Dockerfile en la raíz del contexto de build se usa tal cual y Railpack no interviene.
Preguntas
- ¿Express tiene que escuchar en 0.0.0.0?
- app.listen(port) de Express escucha en todas las interfaces por defecto, que es lo que necesita Codara. No pases 127.0.0.1 ni localhost como host: la plataforma no podría llegar a la app.
- ¿Funciona con Bun, pnpm o Yarn?
- Sí. Railpack elige el gestor de paquetes según el campo packageManager o tu lockfile: pnpm-lock.yaml, bun.lock, yarn.lock o package-lock.json. Sube el lockfile al repositorio.
- ¿Puede mantener conexiones WebSocket?
- Sí. La API funciona como un contenedor siempre activo, no como una función con límite de tiempo. Al publicar una versión, los contenedores antiguos reciben SIGTERM, así que los clientes deben reconectarse.
