Saltar a contenido

Desplegar

Esta guía describe cómo desplegar Camarero-IA en producción: construcción de imágenes con Podman, arranque del pod con todos los servicios, configuración de variables de entorno y uso de los scripts de despliegue automatizado.

El despliegue de producción se realiza sobre Oracle Cloud (Oracle Linux 9, Podman 5.6+) mediante imágenes multi-stage y un pod de Podman que agrupa frontend, backend, base de datos y el proxy NVIDIA.

Dos scripts, dos ámbitos

  • scripts/build-podman.sh se ejecuta en el servidor y gestiona el ciclo de vida local: construir imágenes, crear el pod y arrancar/parar/ver servicios.
  • scripts/deploy-production.sh se ejecuta desde tu máquina local y orquesta el despliegue remoto completo por SSH (sincronizar código, sincronizar variables, construir y reiniciar).

Arquitectura de despliegue

Todos los servicios viven dentro de un único pod de Podman llamado camarero-ia-pod, que comparte red (los contenedores se comunican por localhost).

Contenedor Imagen Puerto publicado
camarero-ia-postgres docker.io/library/postgres:15-alpine 5432
camarero-ia-proxy localhost/camarero-ia-proxy:latest (interno)
camarero-ia-backend localhost/camarero-ia-backend:latest 8000
camarero-ia-frontend localhost/camarero-ia-frontend:latest 3000

Orden de arranque (definido en deploy_pod() de scripts/build-podman.sh):

  1. PostgreSQL — con volumen persistente postgres-data.
  2. Proxy NVIDIA — debe arrancar antes que el backend para estar disponible cuando este lo sondee.
  3. Backend — FastAPI.
  4. Frontend — Next.js en modo standalone.

El frontend usa una imagen multi-stage (frontend/Dockerfile) con tres etapas: deps (dependencias de producción), builder (compilación de Next.js) y runner (runtime mínimo, usuario no-root, HEALTHCHECK incluido).


Requisitos previos

En el servidor (Oracle Cloud):

  • Oracle Linux 9 o compatible.
  • Podman 5.6+ instalado.
  • Firewall configurado (ver Firewall y red).
  • Acceso SSH con clave.

En tu máquina local:

  • rsync y scp (OpenSSH 9+).
  • Clave SSH configurada (por defecto ~/ssh-key-2026-03-21.key).

El proxy NVIDIA vive en una carpeta con espacio

El código del proxy está en ../kilo-nvidia-proxy copy (con un espacio literal en el nombre). Los scripts lo manejan citando la ruta y usando rsync -s / scp en modo SFTP. No renombres esa carpeta sin actualizar PROXY_LOCAL_DIR / PROXY_REMOTE_DIR en scripts/deploy-production.sh y PROXY_DIR en scripts/build-podman.sh.


Despliegue completo (recomendado)

Desde la raíz del repo en tu máquina local:

./scripts/deploy-production.sh deploy

Este comando ejecuta deploy_all(), que encadena todos los pasos:

  1. check_prerequisites — verifica clave SSH, directorio local y rsync.
  2. test_connection — comprueba la conexión SSH al servidor.
  3. sync_files — sincroniza el repo al servidor (excluye node_modules, .next, .git, __pycache__, backend/venv, backend/.env.prod.local).
  4. sync_proxy_files — sincroniza el código del proxy NVIDIA (excluye data, .env, .env.prod.local).
  5. sync_env_file — copia backend/.env.prod.local y le aplica chmod 600.
  6. sync_proxy_env — copia el .env.prod.local del proxy con chmod 600.
  7. sync_proxy_accounts — sube data/accounts.json del proxy solo si el remoto no tiene uno (no pisa las claves vivas).
  8. build_all — construye las tres imágenes (frontend + backend + proxy) en el servidor.
  9. deploy_services — reinicia el pod (build-podman.sh restart).
  10. verify_deployment — comprueba que el pod corre y que el frontend responde HTTP 200; al final hace podman image prune -f.

Migraciones desactivadas en el flujo completo

En deploy_all() el paso run_migrations está comentado. Para aplicar migraciones de base de datos, ejecútalo aparte (ver Migraciones).


Comandos parciales del script de producción

scripts/deploy-production.sh acepta subcomandos para operaciones puntuales:

Comando Acción
deploy Despliegue completo (sincroniza, construye, reinicia, verifica).
sync Solo sincroniza el código del repo (excluye .env).
sync-env Solo sincroniza backend/.env.prod.local.
sync-proxy Solo sincroniza el código del proxy NVIDIA.
sync-proxy-env Solo sincroniza el .env.prod.local del proxy.
sync-proxy-accounts Sube accounts.json solo si el remoto no tiene uno.
migrate Ejecuta las migraciones de base de datos en el servidor.
build Construye las tres imágenes.
build-frontend Construye solo el frontend.
build-backend Construye solo el backend.
build-proxy Construye solo el proxy NVIDIA.
restart Solo reinicia los servicios.
status Muestra el estado del despliegue.
logs Muestra los logs del frontend.
help Muestra la ayuda.

Ejemplos:

./scripts/deploy-production.sh sync-env       # actualizar solo variables de entorno
./scripts/deploy-production.sh build-backend  # reconstruir solo el backend
./scripts/deploy-production.sh status         # ver estado actual

Construcción y gestión local (en el servidor)

scripts/build-podman.sh es el script que se ejecuta dentro del servidor (lo invocan los pasos de deploy-production.sh por SSH, pero también puedes usarlo directamente).

Comando Acción
build Construye las tres imágenes (frontend + backend + proxy).
frontend Construye solo la imagen del frontend.
backend Construye solo la imagen del backend.
proxy Construye solo la imagen del proxy NVIDIA.
deploy Crea el pod y arranca todos los servicios.
stop Para y elimina el pod.
restart Para y vuelve a desplegar el pod.
status Muestra el estado del pod y sus contenedores.
logs <servicio> Muestra los logs de un servicio (frontend, backend, postgres, proxy).
clean Limpia imágenes y contenedores sin usar (podman system prune -f).

Las imágenes se etiquetan como ${REGISTRY_URL}/camarero-ia-{servicio}:${VERSION} (por defecto localhost/...:latest). Puedes sobreescribir el registry y la versión por entorno:

VERSION=v1.0.0 ./scripts/build-podman.sh build

Variables de entorno de producción

Las variables sensibles no se versionan: viven en ficheros .env.prod.local que el script sincroniza con permisos 600.

  • Backend: backend/.env.prod.local → se monta con --env-file en el contenedor del backend.
  • Proxy NVIDIA: <proxy>/.env.prod.local → se monta con --env-file en el contenedor del proxy; además data/accounts.json (claves de NVIDIA) se bind-montea en /data para que persista y sea editable desde el host.

Sin .env.prod.local se usan valores por defecto inseguros

Si backend/.env.prod.local no existe en el servidor, deploy_pod() arranca el backend con un SECRET_KEY de desarrollo y una DATABASE_URL por defecto. No despliegues a producción sin un .env.prod.local real.

Variables esenciales del backend (ver también la guía de configuración si existe):

DATABASE_URL=postgresql+asyncpg://camarero_user:camarero_password@localhost:5432/camarero_db
SECRET_KEY=clave_secreta_de_al_menos_32_caracteres
DEBUG=false

Variables del frontend (se inyectan en deploy_pod() al arrancar el contenedor):

NEXT_PUBLIC_API_URL=https://api.camarero-demo.n0idea.app/api/v1
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1

DATABASE_URL usa asyncpg

El backend (SQLAlchemy 2.x async) requiere el driver asyncpg; el esquema de conexión debe ser postgresql+asyncpg://..., no postgresql://....


Migraciones de base de datos

Las migraciones (Alembic) no se ejecutan en el flujo deploy completo. Para aplicarlas:

./scripts/deploy-production.sh migrate

El paso run_migrations:

  1. Comprueba que el venv del servidor usa Python 3.10+ (necesario por la sintaxis de tipos unión). Si es anterior, aborta con instrucciones para recrear el venv con Python 3.12.
  2. Instala alembic en el venv y ejecuta python -m alembic -c alembic.ini upgrade head.
# Recrear el venv en el servidor (si la versión de Python es < 3.10)
ssh opc@<servidor>
cd ~/camarero-ia/backend
rm -rf venv && python3.12 -m venv venv
source venv/bin/activate && pip install -r requirements.txt

Firewall y red

El frontend se publica en el puerto 3000. Hay que abrirlo tanto en el firewall del servidor como en los Security Groups de Oracle Cloud.

# Firewalld (servidor Oracle Linux)
sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --reload

En Oracle Cloud Infrastructure, añade una regla de ingreso en las Security Lists:

  • Source: 0.0.0.0/0
  • Protocol: TCP
  • Port: 3000

Verificación y operación

Tras desplegar, comprueba el estado y los logs:

# Estado del pod y contenedores (en el servidor)
./scripts/build-podman.sh status

# Logs en tiempo real
./scripts/build-podman.sh logs frontend
./scripts/build-podman.sh logs backend
./scripts/build-podman.sh logs postgres
./scripts/build-podman.sh logs proxy

Comprobaciones manuales útiles:

# Pods y contenedores
podman pod ps
podman ps --filter "pod=camarero-ia-pod"

# Respuesta del frontend
curl -s -o /dev/null -w '%{http_code}' http://localhost:3000   # esperado: 200

# Conexión a PostgreSQL
podman exec -it camarero-ia-postgres \
  psql -U camarero_user -d camarero_db -c "SELECT version();"

URLs de producción

Servicio URL
Frontend http://130.61.243.236:3000 (requiere Security Groups OCI)
API Backend https://api.camarero-demo.n0idea.app
PostgreSQL Interno al pod (puerto 5432)

Solución de problemas

El frontend no es accesible desde fuera

Revisa firewall local y Security Groups de OCI: el puerto 3000 debe estar abierto en ambos.

sudo firewall-cmd --list-ports | grep 3000
./scripts/build-podman.sh logs frontend

Errores de compilación del frontend

Fuerza una reconstrucción limpia:

./scripts/build-podman.sh clean
./scripts/build-podman.sh frontend

La base de datos no está disponible

podman logs camarero-ia-postgres
podman exec -it camarero-ia-postgres psql -U camarero_user -d camarero_db -c "SELECT 1;"

Páginas relacionadas