DocumentaciónGuía para DesarrolladoresGuía Exhaustiva de Despliegue con Docker para 10 Servicios

🐳 Guía Completa de Despliegue con Docker Compose

Manual paso a paso para desplegar los 10 servicios del ecosistema Loomix en un único servidor VPS con máxima seguridad, alta disponibilidad y estabilidad.

1. Requisitos Previos del Servidor (Prerequisites)

Antes de comenzar, prepara un servidor VPS con Ubuntu 22.04 LTS o 24.04 LTS:

  • RAM Mínima: 4GB de RAM física con al menos 4GB de espacio Swap (se recomiendan 8GB de RAM para compilaciones más rápidas).
  • CPU: Al menos 2 núcleos vCPU (se recomiendan 4 vCPU para acelerar las compilaciones de Docker).

Permisos del Socket de Docker

Docker y Docker Compose deben estar instalados y el usuario actual debe pertenecer al grupo docker.

Permisos del Socket de Docker
bash
sudo usermod -aG docker $USER
newgrp docker # or log out and SSH back in
docker ps # should work without sudo

2. Transferencia del Código al Servidor

Puedes transferir los archivos del proyecto a tu VPS mediante cualquiera de estos dos métodos:

Método 1: Clonación Directa con Git (Recomendado)

Mantén Seguras tus Variables de Entorno

Comando para clonar con Git:
bash
git clone https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.git
cd <YOUR_REPOSITORY_NAME>

Clonación desde Repositorio Privado con Claves SSH

  • 1. Genera un par de claves SSH en el servidor: ssh-keygen -t ed25519
  • 2. Muestra y copia la clave pública: cat ~/.ssh/id_ed25519.pub
  • 3. Añade la clave pública en la sección Deploy Keys de tu repositorio en GitHub.
  • 4. Clona el repositorio directamente vía SSH.
Comando para clonar mediante SSH:
bash
git clone git@github.com:<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.git
cd <YOUR_REPOSITORY_NAME>

Clonación con Token de Acceso Personal (PAT)

Comando para clonar con PAT:
bash
git clone https://<YOUR_GITHUB_USERNAME>:<PERSONAL_ACCESS_TOKEN>@github.com/<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.git
cd <YOUR_REPOSITORY_NAME>

Método 2: Subir Archivo Comprimido (ZIP / Tarball)

Si descargaste el código fuente comprimido, súbelo a tu servidor con rsync o scp:

Comando para subir con SCP / rsync:
bash
rsync -avz --exclude 'node_modules' --exclude '.git' --exclude '.next' ./ user@your_vps_ip:/root/next-strapi-medusa

3. Asistente Rápido de Configuración Automática (Quick Wizard)

Para que la instalación sea inmediata, creamos el script server-setup.sh que configura el espacio Swap, audita los puertos e instala los contenedores:

Comando para iniciar el asistente de instalación:
bash
chmod +x server-setup.sh
bash server-setup.sh
Consejo Profesional:
El asistente audita los recursos del servidor y genera automáticamente contraseñas seguras guardándolas en tu archivo .env.

4. Selección del Perfil de Despliegue (Deployment Profiles)

El sistema soporta 3 perfiles de despliegue según tu caso de uso:

¿Necesitas un Dominio Propio?
Sí, para los Perfiles B y C se recomienda un dominio real para que Let's Encrypt emita certificados SSL gratuitos de forma automática.
Recomendado para la Mayoría

Ejecuta todos los servicios en un único servidor VPS con subdominios y certificados SSL automáticos gestionados por Caddy.

Pasos de Configuración para Perfil B:

  • 1. Apunta los registros DNS tipo A a la dirección IP de tu servidor.
  • 2. Selecciona el Perfil B durante la ejecución de server-setup.sh.
  • 3. Introduce tu dominio principal (ej: tudominio.com).
  • 4. Caddy genera certificados SSL automáticos para los 10 servicios.
  • 5. Todos los paneles quedan listos para operar bajo HTTPS.
.env (Fragmento Perfil B)
env
# Profile B: VM / LAN HTTPS (.local hostnames) - Recommended ★
STOREFRONT_PUBLIC_URL=https://store.local
MEDUSA_BACKEND_PUBLIC_URL=https://api.local
STRAPI_PUBLIC_URL=https://admin.local
MEILISEARCH_PUBLIC_URL=https://search.local
MINIO_PUBLIC_URL=https://api.local/minio/mystore
GOOGLE_CALLBACK_URL=https://store.local/ir/account/auth/callback
STOREFRONT_URL=http://storefront:8000
MEDUSA_NODE_ENV=production
MEDUSA_ALLOW_HTTP_COOKIES=false
CLOUDFLARE_TUNNEL_TOKEN=
URLs de Acceso Perfil B:
• Tienda: https://tudominio.com
• Medusa: https://api.tudominio.com/app
• Strapi: https://admin.tudominio.com/admin
• Umami: https://analytics.tudominio.com
• OpenObserve: https://monitor.tudominio.com

Guía de Blindaje de Seguridad en Cloudflare Edge

Antes de Delegar el DNS a Cloudflare:

Para evitar bucles de redirección infinita (Redirect Loops), configura el modo de cifrado SSL en Cloudflare como Full (Strict).

2. Tras el Inicio de los Servicios (Blindaje Posterior al Despliegue):

Modo de Cifrado SSL/TLS: Configurar en Full (Strict).
Certificados Edge: Activar Always Use HTTPS, Automatic HTTPS Rewrites y establecer versión mínima de TLS en TLS 1.2 (o 1.3).
Proxy DNS: Cambiar todos los registros DNS a la nube naranja (Proxied) para aceleración CDN y protección DDoS en el servidor de origen.
Seguridad / WAF: Activar Bot Fight Mode.
Red: Asegurar que WebSockets y gRPC estén habilitados.
Caché: En Caching > Configuration, verificar que Browser Cache TTL esté en Respect Existing Headers para preservar actualizaciones instantáneas de carrito e inventario.

HTTP Basic Auth y Protección Edge con Caddy:

Panel de Administración de Strapi (admin.tudominio.com/admin* y /): Protegido con HTTP Basic Auth para evitar ataques de fuerza bruta. Las rutas públicas de API (/api/*) y los archivos multimedia (/uploads/*) permanecen accesibles para que el Storefront y Medusa consulten datos sin errores 401.
Panel de OpenObserve (monitor.tudominio.com): Protegido con HTTP Basic Auth como doble capa de defensa junto a las credenciales internas de OpenObserve.

Genera un hash bcrypt seguro para BASIC_AUTH_HASH en .env con:

Generar Hash de Contraseña Bcrypt para Caddy
bash
docker run --rm caddy:latest caddy hash-password --plaintext "your_secret_password"

Matriz de URLs y Puertos según el Perfil

ServicioPerfil A (Local)Perfil B (VPS Único)Perfil C (Empresarial)
Tienda Next.jshttp://<VM_IP>:8000https://store.localhttps://yourdomain.com
Backend Medusahttp://<VM_IP>:9000/apphttps://api.local/apphttps://api.yourdomain.com/app
Panel Strapi CMShttp://<VM_IP>:1337/adminhttps://admin.local/adminhttps://admin.yourdomain.com/admin
Analítica Umamihttp://<VM_IP>:3005https://analytics.localhttps://analytics.yourdomain.com
Monitorización OpenObservehttp://<VM_IP>:5080https://monitor.localhttps://monitor.yourdomain.com
Motor de Búsqueda (Meilisearch)127.0.0.1:7700https://search.localhttps://search.yourdomain.com

Significado de cada URL Pública en .env:

  • STOREFRONT_PUBLIC_URL: Tienda Next.js (puerto 8000 dentro de Docker o dominio público).
  • MEDUSA_BACKEND_PUBLIC_URL: Medusa API y Panel de Administración (/app).
  • STRAPI_PUBLIC_URL: Strapi CMS (/admin); los enlaces de vista previa usan STOREFRONT_PUBLIC_URL.
  • MEILISEARCH_PUBLIC_URL: URL pública para búsquedas instantáneas en cliente (Perfil A: http://127.0.0.1:7700, Perfil B: https://search.local, Perfil C: https://search.tudominio.com).
  • MINIO_PUBLIC_URL: Prefijo público para archivos multimedia (Perfil A: http://IP:9001/mystore, Perfil B/C: https://api.*/minio/mystore).
  • STOREFRONT_URL: Solo para red interna de Docker (http://storefront:8000), utilizado para revalidación de caché Medusa -> Storefront.

Configurar OBLIGATORIAMENTE antes de la Fase 1:

Claves Secretas (openssl rand -hex 32): POSTGRES_PASSWORD, MEILI_MASTER_KEY, todas las claves STRAPI_*, MEDUSA_JWT_SECRET, MEDUSA_COOKIE_SECRET, REVALIDATE_SECRET, UMAMI_APP_SECRET.
Credenciales de Administración: MEDUSA_ADMIN_EMAIL, MEDUSA_ADMIN_PASSWORD, MINIO_ROOT_USER, MINIO_ROOT_PASSWORD, UMAMI_USERNAME, UMAMI_PASSWORD.
URLs Públicas: Selecciona el Perfil A, B o C indicado arriba.

Dejar vacías hasta llegar a la fase correspondiente:

• Fase 4: STRAPI_API_TOKEN_FOR_MEDUSA, STRAPI_API_TOKEN_FOR_FRONT
• Fase 6: MEDUSA_PUBLISHABLE_KEY
• Fase 7: MEILI_SEARCH_KEY
• Fase 8: UMAMI_WEBSITE_ID

Regla del Panel Medusa: Mantén siempre MEDUSA_NODE_ENV=production en Docker. Nunca configures development; el panel está compilado para producción y el modo dev causa pantalla blanca.

5. Despliegue Automatizado con GitHub Actions CI/CD

El proyecto incluye flujos de trabajo preconfigurados para compilar los contenedores Docker y desplegarlos en tu VPS en cada push:

  1. Añade la IP de tu servidor y la clave privada SSH a los Secretos del Repositorio (Repository Secrets).
  2. Cada envío a la rama main compila y optimiza los contenedores de Next.js y Medusa.
  3. Se envía una señal al servidor para realizar una actualización en caliente sin tiempo de inactividad (Zero-Downtime).
  4. 4. (Repositorio privado) Genera un GitHub Personal Access Token (Classic) con permisos repo, workflow y read:packages, luego inicia sesión en GitHub Container Registry en tu VPS:
Inicio de Sesión en Docker Registry en VPS
bash
echo "<YOUR_PAT>" | docker login ghcr.io -u <YOUR_GITHUB_USERNAME> --password-stdin

Proceso de Despliegue en 10 Fases (Phases 1-10)

FaseServicios IniciadosPerfil APerfil B / C (Red Local y Producción)
Fase 1:Bases de Datos e Infraestructura (Postgres, Redis, MinIO, Meilisearch)
Fase 2:Proxy Inverso Caddy y SSL Automático (hosts en Perfil B)⏭ Omitir (No requerido en Perfil A)✅ Inmediatamente después de la Fase 1, antes de Strapi
Fase 3:Motor Strapi CMS (Descarga de imagen desde GHCR)
Fase 4:Tokens de API de Strapi -> guardar en .env
Fase 5:Motor Comercial Medusa 2.0 (Descarga de imagen desde GHCR)
Fase 6:Clave Pública de Medusa -> guardar en .env
Fase 7:Clave de Solo Búsqueda de Meilisearch -> guardar en .env
Fase 8:Analítica con Umami (Antes de la tienda)Opcional
Fase 9:Frontend Next.js (Compilación y Despliegue con GitHub Actions)
Fase 10:Stack de Observabilidad y Logs (OpenObserve, Vector, cAdvisor)OpcionalRecomendado

Fase 1: Inicio de Bases de Datos (PostgreSQL & Redis)

Se inicializa PostgreSQL con esquemas aislados para Medusa, Strapi y Umami, junto con Redis para sesiones y caché en memoria.

Comando para Fase 1:
bash
docker compose up -d postgres redis meilisearch minio minio-setup

Espera hasta que todos los servicios estén saludables (healthy): docker compose ps

Fase 2: Pasarela Caddy y Certificados SSL Automáticos

Se ejecuta el servicio de proxy inverso Caddy para suministrar certificados SSL Let's Encrypt de forma transparente.

Comando para Fase 2:
bash
docker compose up -d caddy
docker compose logs -f caddy

Configuración del archivo hosts en Windows para Perfil B:

Abre C:\Windows\System32\drivers\etc\hosts como Administrador y añade:
192.168.1.103 store.local api.local admin.local analytics.local monitor.local
(Reemplaza 192.168.1.103 con la IP de tu VM. No agregues Meilisearch; debe permanecer interno).

Fase 3: Inicio de Strapi CMS v5

Se descarga la imagen de Strapi CMS, se conecta a la base de datos y se espera a que el puerto 1337 esté listo.

Comando para Fase 3:
bash
docker compose pull strapi
docker compose up -d strapi
docker compose logs -f strapi

Espera a que el servidor escuche en el puerto 1337 (1–3 minutos en el primer inicio). Abre el panel de Strapi (Perfil B: https://admin.local/admin, Perfil A: http://<VM_IP>:1337/admin) y registra tu cuenta de administrador.

Fase 4: Extracción de Claves de API de Strapi e Inyección en .env

Se genera automáticamente el token de acceso para que el frontend de Next.js pueda consultar los bloques y se escribe en .env.

  1. El script strapi-token-init.js se ejecuta para extraer el token administrativo.
  2. La variable STRAPI_API_TOKEN se guarda en el archivo .env.
  3. 3. Para la Tienda (STRAPI_API_TOKEN_FOR_FRONT): Haz clic en el token Read-Only, pulsa Regenerate y copia el valor en STRAPI_API_TOKEN_FOR_FRONT en tu .env.

Fase 5: Inicio del Motor de Comercio MedusaJS v2

Se ejecuta el contenedor de Medusa, se aplican las migraciones de base de datos y se crea el primer usuario superadministrador.

Comando para Fase 5:
bash
docker compose pull medusa
docker compose up -d medusa
docker compose logs -f medusa

Pasos automáticos en el primer inicio: Migraciones de BD con db:migrate (2–5 minutos) -> creación de superadministrador -> API lista en el puerto 9000. Abre Medusa Admin en https://api.local/app (Perfil B) o http://<VM_IP>:9000/app (Perfil A) e inicia sesión con MEDUSA_ADMIN_EMAIL y MEDUSA_ADMIN_PASSWORD.

Fase 6: Canales de Venta y Claves Publicables de Medusa

Se genera la clave publicable para que el frontend gestione carritos y productos vinculados al canal de venta por defecto.

  1. El usuario administrador queda creado y autorizado.
  2. La clave publicable se asigna a la variable NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY.
  3. 3. MUY IMPORTANTE: Abre la clave creada > pestaña Sales Channels > vincula con Default Sales Channel. Sin este paso, los productos no aparecerán en la tienda.

Fase 7: Despliegue del Motor de Búsqueda Meilisearch

Se arranca el contenedor de Meilisearch para ofrecer búsquedas instantáneas y tolerancia a fallos tipográficos.

Comando para Fase 7:
bash
curl -H "Authorization: Bearer <MEILI_MASTER_KEY>" http://127.0.0.1:7700/keys

Copia la Default Search API Key y colócala en MEILI_SEARCH_KEY en tu .env (el asistente interactivo la extrae automáticamente).

Fase 8: Inicio de la Plataforma de Analítica Umami

Se ejecuta Umami, plataforma analítica independiente y libre de cookies, configurando el identificador del sitio web.

Comando para Fase 8:
bash
docker compose up -d umami

Abre el panel de Umami (Perfil B: https://analytics.local, Perfil A: http://<VM_IP>:3005). Inicia sesión (admin / umami), ve a Settings > Websites > Add website y copia el Website ID generado en UMAMI_WEBSITE_ID en tu .env.

Fase 9: Despliegue del Escaparate Next.js 16

Se compila y ejecuta el frontend conectándose a todos los servicios preparados, dejando la tienda disponible al público.

1. Variables de Compilación y Claves de API:

Las rutas de Medusa y Strapi se inyectan en el contenedor durante la fase de compilación.

1. STOREFRONT_BUILD_ARGS (Variables de Compilación)

Contiene las variables de compilación de Next.js. Copia la plantilla anterior e introduce las claves generadas en las fases previas.

Argumentos de Compilación (Build Args):
env
MEDUSA_BACKEND_URL=http://medusa:9000
NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api.yourdomain.com
NEXT_PUBLIC_STRAPI_URL=https://admin.yourdomain.com
NEXT_PUBLIC_BASE_URL=https://store.yourdomain.com
NEXT_PUBLIC_MEILISEARCH_HOST=https://search.yourdomain.com
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_...
NEXT_PUBLIC_MEILISEARCH_SEARCH_KEY=...
NEXT_PUBLIC_UMAMI_WEBSITE_ID=...
NEXT_PUBLIC_DEFAULT_REGION=US
DEFAULT_LOCALE=en-US
NEXT_PUBLIC_MEILISEARCH_INDEX_NAME=products
NEXT_PUBLIC_ENABLE_IRAN_FEATURES=false

2. REGISTRY_URL

URL del registro de componentes. Valor por defecto: Registro público de Loomix Blocks:
https://raw.githubusercontent.com/landa33/loom-blocks-registry/main/src/modules

3. GITHUB_PAT (Opcional)

GitHub Personal Access Token (Classic). Requiere permisos repo, workflow y read:packages. Utilizado para descargas de GHCR, activación de CI/CD y acceso a registros privados.

4. DEPLOY_PATH

Ruta absoluta al directorio del proyecto en tu VPS Linux (ej. /root/loomix-commerce). Obligatorio para que el Self-Hosted Runner localice el proyecto de Docker Compose.

2. Salida Standalone Ultraligera:

La compilación Standalone de Next.js reduce el tamaño de la imagen final por debajo de 150MB.

3. Comprobación de Red y Disponibilidad:

Se audita el puerto 8000 y se enlaza con la red del proxy inverso Caddy.

4. Lanzamiento del Escaparate en Producción:

Comando para ejecutar el frontend:
bash
docker compose pull storefront
docker compose up -d storefront

Fase 10: Observabilidad y Monitorización de Registros (OpenObserve & Vector)

Se activan Vector y OpenObserve para recolectar métricas del sistema, uso de memoria, CPU y registros de contenedores.

Comando para Fase 10:
bash
docker compose up -d openobserve vector cadvisor docker-stats-exporter

Panel Central de Control de OpenObserve:

Abre https://monitor.tudominio.com (Perfil C), https://monitor.local (Perfil B) o http://<VM_IP>:5080 (Perfil A). Inicia sesión con tus credenciales root de OpenObserve.

Flujos de Telemetría y Registros Recolectados:

docker_logs: Registros unificados de los contenedores y búsqueda instantánea de errores en todos los microservicios.

caddy_access: Tráfico web HTTP en vivo, direcciones IP, códigos de estado HTTP (2xx/4xx/5xx) y rutas de solicitud emitidas directamente desde los logs JSON de Caddy vía Vector.

docker_stats: Porcentaje de uso de memoria en tiempo real, consumo de CPU % y E/S de red por contenedor mediante cAdvisor.

host_metrics: Carga general de CPU, utilización de RAM y métricas de E/S de disco a nivel del servidor host.

Notificaciones Inmediatas de Alertas en Telegram:

En el panel de OpenObserve, navega a Reliability > Destinations para vincular el webhook de tu bot de Telegram (https://api.telegram.org/bot<TOKEN>/sendMessage), luego crea reglas de alerta en Reliability > Alerts para avisos en tiempo real ante errores 500.

6. Sincronización Inicial de Datos entre Medusa y Strapi

Procedimiento automático que lee productos y categorías en Medusa y genera los bloques correspondientes en Strapi.

Ejecutar la Primera Sincronización:

Ejecuta el siguiente comando dentro del contenedor de Strapi para generar la portada por defecto:

2. Sincronización de Bloques Modulares Loomix (sync-loom-component.js)

En el panel de Strapi Storefront Management, hacer clic en + Add to Storefront (Queue) o Remove Style (Queue) pone los cambios en cola en sync-history.json. Al pulsar Update Storefront, se sincronizan los ajustes preestablecidos y se dispara la compilación y despliegue en GitHub Actions.

Variables de Entorno para Sincronización en Producción:

Coloca estas variables en website-admin/.env y en el archivo raíz .env del servidor. Asegúrate de que el token tenga permisos 'repo' y 'workflow':

Variables de Sincronización para GitHub CI/CD
env
GITHUB_DEPLOY_TOKEN=ghp_your_personal_access_token # Requires 'repo' and 'workflow' scopes
GITHUB_DEPLOY_REPO=your_username/your_repo_name

7. Cambio entre Perfiles de Despliegue

Para migrar de Perfil A a Perfil B o modificar los dominios asignados, sigue estas pautas:

Tipo de CambioServicios a Reiniciar
URLs públicas en .envStrapi, Medusa, Storefront (inicia la acción de GitHub Actions primero, luego descarga)
Ajuste MEDUSA_ALLOW_HTTP_COOKIESSolo contenedor Medusa
Añadir Caddy (Transición de A a B)Iniciar Caddy (docker compose up -d caddy); descargar nuevas imágenes
Archivo hosts (Perfil B)Nada en el servidor; solo edita el archivo hosts de Windows en tu máquina
Ejemplo de Cambio de Perfil
bash
# 1. Edit .env — switch to Profile B URLs, set MEDUSA_ALLOW_HTTP_COOKIES=false
nano .env
# 2. Add hosts entry on Windows
# 3. Start Caddy
docker compose up -d caddy
# 4. Pull new images:
docker compose pull strapi medusa && docker compose up -d strapi medusa

8. Actualización de Servicios a la Última Versión

Ejecuta el script server-update.sh para descargar las versiones más recientes sin perder ningún dato de la base de datos.

9. Comandos Útiles de Mantenimiento y Administración

Comandos de Docker para supervisar registros, reiniciar servicios y realizar copias de seguridad:

Comandos de Mantenimiento Habitual:
bash
./setup.sh # On Linux / macOS
.\setup.bat # On Windows

10. Topología de Red Interna y Mapa de Puertos

Red Puente Interna entre Contenedores (Internal Bridge Network):

  • Tienda (Storefront): :8000
  • Medusa API + Administración: :9000
  • Strapi CMS: :1337
  • Meilisearch: :7700
  • Consola MinIO: :9001
  • Analítica Umami: :3005
  • Monitorización OpenObserve: :5080

Nombres de Dominio Gestionados por Caddy:

  • https://store.local -> storefront:8000
  • https://api.local -> medusa:9000
  • https://admin.local -> strapi:1337
  • https://analytics.local -> umami:3000
  • https://monitor.local -> openobserve:5080
  • https://api.local/minio/ -> minio:9000

Red Aislada de Contenedores loomix-network:

Los contenedores se comunican internamente mediante nombres de servicio estándar (ej. http://storefront:8000, http://medusa:9000, http://meilisearch:7700). Meilisearch es estrictamente interno y nunca debe exponerse públicamente.

Resumen de Comandos Principales de Gestión

Supervisar registros en tiempo real de todos los servicios:
bash
docker compose ps
Reiniciar un contenedor específico:
bash
docker compose logs -f medusa
docker compose logs -f strapi
docker compose logs -f storefront
docker compose logs -f openobserve
Detener el ecosistema completo:
bash
docker builder prune -f
docker system prune -f
Reinicio Completo (conservando volúmenes y bases de datos)
bash
docker compose down
docker compose up -d