🐳 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.
sudo usermod -aG docker $USERnewgrp docker # or log out and SSH back indocker ps # should work without sudo2. 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
git clone https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.gitcd <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.
git clone git@github.com:<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.gitcd <YOUR_REPOSITORY_NAME>Clonación con Token de Acceso Personal (PAT)
git clone https://<YOUR_GITHUB_USERNAME>:<PERSONAL_ACCESS_TOKEN>@github.com/<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.gitcd <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:
rsync -avz --exclude 'node_modules' --exclude '.git' --exclude '.next' ./ user@your_vps_ip:/root/next-strapi-medusa3. 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:
chmod +x server-setup.shbash server-setup.shConsejo Profesional:
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?
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.
# Profile B: VM / LAN HTTPS (.local hostnames) - Recommended ★ STOREFRONT_PUBLIC_URL=https://store.localMEDUSA_BACKEND_PUBLIC_URL=https://api.localSTRAPI_PUBLIC_URL=https://admin.localMEILISEARCH_PUBLIC_URL=https://search.localMINIO_PUBLIC_URL=https://api.local/minio/mystoreGOOGLE_CALLBACK_URL=https://store.local/ir/account/auth/callback STOREFRONT_URL=http://storefront:8000MEDUSA_NODE_ENV=productionMEDUSA_ALLOW_HTTP_COOKIES=falseCLOUDFLARE_TUNNEL_TOKEN=• 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.comGuí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:
docker run --rm caddy:latest caddy hash-password --plaintext "your_secret_password"Matriz de URLs y Puertos según el Perfil
| Servicio | Perfil A (Local) | Perfil B (VPS Único) | Perfil C (Empresarial) |
|---|---|---|---|
| Tienda Next.js | http://<VM_IP>:8000 | https://store.local | https://yourdomain.com |
| Backend Medusa | http://<VM_IP>:9000/app | https://api.local/app | https://api.yourdomain.com/app |
| Panel Strapi CMS | http://<VM_IP>:1337/admin | https://admin.local/admin | https://admin.yourdomain.com/admin |
| Analítica Umami | http://<VM_IP>:3005 | https://analytics.local | https://analytics.yourdomain.com |
| Monitorización OpenObserve | http://<VM_IP>:5080 | https://monitor.local | https://monitor.yourdomain.com |
| Motor de Búsqueda (Meilisearch) | 127.0.0.1:7700 | https://search.local | https://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:
- Añade la IP de tu servidor y la clave privada SSH a los Secretos del Repositorio (Repository Secrets).
- Cada envío a la rama main compila y optimiza los contenedores de Next.js y Medusa.
- Se envía una señal al servidor para realizar una actualización en caliente sin tiempo de inactividad (Zero-Downtime).
- 4. (Repositorio privado) Genera un GitHub Personal Access Token (Classic) con permisos
repo,workflowyread:packages, luego inicia sesión en GitHub Container Registry en tu VPS:
echo "<YOUR_PAT>" | docker login ghcr.io -u <YOUR_GITHUB_USERNAME> --password-stdinProceso de Despliegue en 10 Fases (Phases 1-10)
| Fase | Servicios Iniciados | Perfil A | Perfil 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) | Opcional | Recomendado |
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.
docker compose up -d postgres redis meilisearch minio minio-setupEspera 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.
docker compose up -d caddydocker compose logs -f caddyConfiguració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.
docker compose pull strapidocker compose up -d strapidocker compose logs -f strapiEspera 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.
- El script strapi-token-init.js se ejecuta para extraer el token administrativo.
- La variable STRAPI_API_TOKEN se guarda en el archivo .env.
- 3. Para la Tienda (
STRAPI_API_TOKEN_FOR_FRONT): Haz clic en el tokenRead-Only, pulsa Regenerate y copia el valor enSTRAPI_API_TOKEN_FOR_FRONTen 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.
docker compose pull medusadocker compose up -d medusadocker compose logs -f medusaPasos 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.
- El usuario administrador queda creado y autorizado.
- La clave publicable se asigna a la variable NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY.
- 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.
curl -H "Authorization: Bearer <MEILI_MASTER_KEY>" http://127.0.0.1:7700/keysCopia 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.
docker compose up -d umamiAbre 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.
MEDUSA_BACKEND_URL=http://medusa:9000NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api.yourdomain.comNEXT_PUBLIC_STRAPI_URL=https://admin.yourdomain.comNEXT_PUBLIC_BASE_URL=https://store.yourdomain.comNEXT_PUBLIC_MEILISEARCH_HOST=https://search.yourdomain.comNEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_...NEXT_PUBLIC_MEILISEARCH_SEARCH_KEY=...NEXT_PUBLIC_UMAMI_WEBSITE_ID=...NEXT_PUBLIC_DEFAULT_REGION=USDEFAULT_LOCALE=en-USNEXT_PUBLIC_MEILISEARCH_INDEX_NAME=productsNEXT_PUBLIC_ENABLE_IRAN_FEATURES=false2. 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:
docker compose pull storefrontdocker compose up -d storefrontFase 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.
docker compose up -d openobserve vector cadvisor docker-stats-exporterPanel 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':
GITHUB_DEPLOY_TOKEN=ghp_your_personal_access_token # Requires 'repo' and 'workflow' scopesGITHUB_DEPLOY_REPO=your_username/your_repo_name7. Cambio entre Perfiles de Despliegue
Para migrar de Perfil A a Perfil B o modificar los dominios asignados, sigue estas pautas:
| Tipo de Cambio | Servicios a Reiniciar |
|---|---|
| URLs públicas en .env | Strapi, Medusa, Storefront (inicia la acción de GitHub Actions primero, luego descarga) |
| Ajuste MEDUSA_ALLOW_HTTP_COOKIES | Solo 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 |
# 1. Edit .env — switch to Profile B URLs, set MEDUSA_ALLOW_HTTP_COOKIES=falsenano .env # 2. Add hosts entry on Windows # 3. Start Caddydocker compose up -d caddy # 4. Pull new images:docker compose pull strapi medusa && docker compose up -d strapi medusa8. 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:
./setup.sh # On Linux / macOS.\setup.bat # On Windows10. 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
docker compose psdocker compose logs -f medusadocker compose logs -f strapidocker compose logs -f storefrontdocker compose logs -f openobservedocker builder prune -fdocker system prune -fdocker compose downdocker compose up -d