Files
Portainer/ruleta/README.md
Eduardo David Paredes Vara f29208cfa2 middelware fix
2026-02-17 08:57:58 +00:00

10 KiB

Ruleta - Aplicación Next.js

Aplicación web personalizada construida con Next.js.

📋 Descripción

Este stack despliega una aplicación Next.js con:

  • Dos rutas de acceso: subdominio y path
  • Integración con Traefik para HTTPS
  • Soporte para múltiples dominios
  • Configuración opcional de Authentik (SSO)

🚀 Despliegue

Prerequisitos

  1. Red Docker: Asegúrate de que la red proxy existe
  2. Registros DNS: Configura los registros A para tus dominios
  3. Imagen Docker: La aplicación debe estar construida como imagen Docker

Desde Portainer

  1. Ve a StacksAdd stack
  2. Nombre: ruleta
  3. Selecciona Repository o Git repository
  4. Configura:
    • Repository URL: <tu-repositorio>
    • Repository reference: main
    • Compose path: ruleta/docker-compose.yml
  5. Carga el archivo de variables de entorno: ruleta/stack.env
  6. Haz clic en Deploy the stack

Variables de Entorno

Edita el archivo stack.env:

# Imagen de la aplicación (construida previamente)
RULETA_IMAGE=tu-usuario/ruleta:latest

# Entorno de Node.js
RULETA_NODE_ENV=production
RULETA_NEXT_TELEMETRY_DISABLED=1

# Puerto interno de Next.js
RULETA_APP_PORT=3000

# Dominios
# Opción 1: Subdominio dedicado
RULETA_SUBDOMAIN=ruleta.tudominio.com

# Opción 2: Path en dominio principal
RULETA_MAIN_DOMAIN=tudominio.com

# Traefik
TRAEFIK_DOCKER_NETWORK=proxy
TRAEFIK_ENTRYPOINT_SECURE=websecure
TRAEFIK_CERTRESOLVER=letsencrypt

# Si usas Supabase, descomenta y configura:
# NEXT_PUBLIC_SUPABASE_URL=https://tu-proyecto.supabase.co
# NEXT_PUBLIC_SUPABASE_ANON_KEY=tu-clave-publica
# SUPABASE_SERVICE_ROLE_KEY=tu-clave-privada

⚙️ Rutas de Acceso

Esta aplicación tiene dos formas de acceso configuradas:

1. Subdominio Dedicado

Accede mediante: https://ruleta.tudominio.com

  • URL completa del subdominio
  • Next.js recibe las peticiones en el path raíz /
  • No requiere configuración especial en Next.js

2. Path en Dominio Principal

Accede mediante: https://tudominio.com/ruleta

  • Path dentro del dominio principal
  • Traefik elimina el prefijo /ruleta antes de enviar a Next.js
  • Next.js recibe las peticiones como si estuvieran en /

Nota: Puedes usar ambas rutas simultáneamente o deshabilitar una editando el docker-compose.yml.

🔧 Configuración de Next.js

Configurar basePath (si usas path)

Si quieres que Next.js sea consciente del path /ruleta, edita next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  basePath: '/ruleta',
  assetPrefix: '/ruleta',
  // ... otras opciones
}

module.exports = nextConfig

Nota: Con la configuración actual (middleware de stripprefix en Traefik), esto NO es necesario. Traefik se encarga de eliminar el prefijo.

Variables de Entorno en Next.js

Para exponer variables al cliente (navegador):

// next.config.js
module.exports = {
  env: {
    CUSTOM_VAR: process.env.CUSTOM_VAR,
  },
  // o usa NEXT_PUBLIC_ prefix
}

En stack.env:

NEXT_PUBLIC_API_URL=https://api.tudominio.com
CUSTOM_VAR=valor-personalizado

🔒 Proteger con Authentik (Opcional)

Por defecto, la aplicación NO está protegida con SSO. Para protegerla:

Opción 1: Proteger Todo

Edita el docker-compose.yml y descomenta:

labels:
  # Para subdominio
  traefik.http.routers.ruleta-sub.middlewares: "ths-authentik@docker"
  
  # Para path (requiere cadena de middlewares)
  traefik.http.routers.ruleta-path.middlewares: "ths-authentik@docker,ruleta-strip@docker"

Opción 2: Proteger Solo Ciertas Rutas

Crea routers adicionales en Traefik:

# Router para rutas públicas
traefik.http.routers.ruleta-public.rule: "Host(`ruleta.tudominio.com`) && PathPrefix(`/api`, `/public`)"
traefik.http.routers.ruleta-public.priority: "20"

# Router para rutas protegidas
traefik.http.routers.ruleta-private.rule: "Host(`ruleta.tudominio.com`) && PathPrefix(`/admin`)"
traefik.http.routers.ruleta-private.middlewares: "ths-authentik@docker"
traefik.http.routers.ruleta-private.priority: "30"

🏗️ Construir la Imagen Docker

Dockerfile de Ejemplo

# Build stage
FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine AS runner

WORKDIR /app
ENV NODE_ENV=production

# Copiar archivos necesarios
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 3000
CMD ["node", "server.js"]

next.config.js para Standalone

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
  // ... otras opciones
}

module.exports = nextConfig

Construir y Publicar

# Construir
docker build -t tu-usuario/ruleta:latest .

# Probar localmente
docker run -p 3000:3000 tu-usuario/ruleta:latest

# Publicar en Docker Hub
docker push tu-usuario/ruleta:latest

# O publicar en GitHub Container Registry
docker tag tu-usuario/ruleta:latest ghcr.io/tu-usuario/ruleta:latest
docker push ghcr.io/tu-usuario/ruleta:latest

🔧 Configuración Avanzada

Integración con Supabase

Si tu aplicación usa Supabase:

  1. Crea un proyecto en supabase.com

  2. Obtén las credenciales:

    • URL del proyecto: Settings → API → Project URL
    • Anon key: Settings → API → anon public
    • Service role key: Settings → API → service_role (secreto)
  3. Añade a stack.env:

    NEXT_PUBLIC_SUPABASE_URL=https://tu-proyecto.supabase.co
    NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbG...
    SUPABASE_SERVICE_ROLE_KEY=eyJhbG...
    
  4. En tu código Next.js:

    import { createClient } from '@supabase/supabase-js'
    
    const supabase = createClient(
      process.env.NEXT_PUBLIC_SUPABASE_URL,
      process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
    )
    

Variables de Entorno Sensibles

Para secrets (API keys, tokens):

  1. No las incluyas en stack.env si el repositorio es público

  2. Configúralas manualmente en Portainer:

    • Edita el stack
    • Ve a la pestaña Environment variables
    • Añade variables adicionales
  3. O usa Docker secrets:

    services:
      app:
        secrets:
          - api_key
    
    secrets:
      api_key:
        external: true
    

Volúmenes para Datos Persistentes

Si necesitas persistir datos (uploads, cache):

services:
  app:
    volumes:
      - ${RULETA_DATA_PATH}:/app/data:Z
      - ${RULETA_UPLOADS_PATH}:/app/public/uploads:Z

Añade a stack.env:

RULETA_DATA_PATH=/opt/ruleta/data
RULETA_UPLOADS_PATH=/opt/ruleta/uploads

🛠️ Troubleshooting

La aplicación no inicia

  1. Verifica los logs:

    docker logs ruleta-app
    
  2. Verifica que la imagen existe:

    docker images | grep ruleta
    
  3. Verifica variables de entorno:

    docker inspect ruleta-app | grep -A 20 Env
    

No puedo acceder por dominio

  1. Verifica DNS:

    nslookup ruleta.tudominio.com
    
  2. Verifica Traefik:

    docker logs traefik | grep ruleta
    
  3. Verifica labels de Traefik:

    docker inspect ruleta-app | grep -A 30 Labels
    

Error 502 Bad Gateway

  1. Verifica que el puerto interno es correcto:

    • Next.js por defecto usa puerto 3000
    • Verifica RULETA_APP_PORT=3000
  2. Verifica que la aplicación está escuchando:

    docker exec ruleta-app netstat -tulpn
    
  3. Verifica conectividad desde Traefik:

    docker exec traefik ping ruleta-app
    

Las rutas no funcionan con basePath

Si configuraste basePath en Next.js:

  1. Opción A: Elimina el middleware stripprefix de Traefik
  2. Opción B: Elimina basePath de Next.js (Traefik se encarga)

Recursos estáticos (CSS/JS) no cargan

Verifica:

  1. El assetPrefix en next.config.js (debe coincidir con basePath)
  2. Los logs del navegador (F12 → Console)
  3. Las rutas en el inspector de red (F12 → Network)

Variables de entorno no disponibles

Recuerda:

  • Solo variables con prefijo NEXT_PUBLIC_ están disponibles en el navegador
  • Variables sin prefijo solo están disponibles en el servidor (API routes, getServerSideProps)

📚 Recursos Adicionales

🔄 Actualizaciones

Actualizar la Aplicación

  1. Construye una nueva versión de la imagen:

    docker build -t tu-usuario/ruleta:v2.0 .
    docker push tu-usuario/ruleta:v2.0
    
  2. Actualiza en stack.env:

    RULETA_IMAGE=tu-usuario/ruleta:v2.0
    
  3. Actualiza el stack en Portainer

Rolling Updates

Para actualizaciones sin downtime, usa múltiples réplicas (requiere Docker Swarm o Kubernetes).

Rollback

Si algo sale mal:

  1. Vuelve a la versión anterior en stack.env
  2. Actualiza el stack en Portainer

📊 Monitoreo

Logs de la Aplicación

# Logs en tiempo real
docker logs -f ruleta-app

# Últimas 100 líneas
docker logs --tail 100 ruleta-app

# Logs con timestamps
docker logs -t ruleta-app

Logs de Next.js

Next.js registra en stdout/stderr, accesibles con docker logs.

Para logs estructurados, considera usar:

Métricas

Para monitorear la aplicación:

  1. Implementa un endpoint /api/health
  2. Usa herramientas como Prometheus + Grafana
  3. O servicios de APM como New Relic, Datadog

🎯 Casos de Uso

Este stack es ideal para:

  • Aplicaciones Next.js personalizadas
  • Landing pages
  • Dashboards administrativos
  • Aplicaciones full-stack con API routes
  • JAMstack con SSR/SSG

💡 Tips

  • Usa output: 'standalone' en Next.js para imágenes Docker más pequeñas
  • Implementa caching con Redis para mejor rendimiento
  • Usa ISR (Incremental Static Regeneration) para contenido dinámico
  • Implementa rate limiting en API routes
  • Usa CDN para assets estáticos (imágenes, CSS, JS)