8.5 KiB
🎯 Nuevo Enfoque de CI/CD - Script de Deployment en el Host
El Problema que Resolvimos
❌ Enfoque Anterior (No Funcionaba)
El workflow intentaba ejecutar comandos docker directamente dentro del contenedor del runner:
- name: Construir Imágenes
run: |
docker compose -f docker-compose_prod.yml build
Problema: Aunque el socket de Docker estaba montado (/var/run/docker.sock), el binario docker no estaba disponible dentro del contenedor del runner, causando el error:
docker: command not found
✅ Nuevo Enfoque (Funciona)
Creamos un script deploy.sh que se ejecuta directamente en el host, donde Docker SÍ está instalado:
- name: Ejecutar Deployment
run: |
cd /home/marti/Documentos/Gitea/resistencia
./deploy.sh
Arquitectura del Nuevo Sistema
┌─────────────────────────────────────────────────────────────┐
│ GITEA SERVER │
│ - Detecta push a main │
│ - Envía job al runner │
└────────────────┬────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ GITEA RUNNER (Contenedor) │
│ - Instala Node.js │
│ - Hace checkout del código │
│ - Ejecuta deploy.sh en el HOST │
└────────────────┬────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ HOST (Servidor de Producción) │
│ - deploy.sh se ejecuta aquí │
│ - Docker está instalado aquí │
│ - Construye y despliega contenedores │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Client │ │ Server │ │ Database │ │
│ │ (Next.js) │ │ (Node.js) │ │ (PostgreSQL) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
Componentes del Sistema
1. deploy.sh - Script de Deployment en el Host
Ubicación: /home/marti/Documentos/Gitea/resistencia/deploy.sh
Responsabilidades:
- ✅ Actualizar código desde Git
- ✅ Detener contenedores anteriores
- ✅ Limpiar imágenes antiguas
- ✅ Construir nuevas imágenes Docker
- ✅ Desplegar contenedores
- ✅ Verificar que todo funciona
- ✅ Mostrar logs
Ventajas:
- Se ejecuta directamente en el host donde Docker está instalado
- Puede ser ejecutado manualmente para debugging:
./deploy.sh - Fácil de modificar y probar
- No depende de las limitaciones del runner
2. .gitea/workflows/deployment.yml - Workflow Simplificado
Responsabilidades:
- ✅ Instalar Node.js (necesario para
actions/checkout) - ✅ Hacer checkout del código
- ✅ Ejecutar
deploy.shen el host - ✅ Verificar el resultado
Ventajas:
- Mucho más simple y mantenible
- Menos propenso a errores
- Fácil de entender y debuggear
Cómo Funciona
Flujo Completo
-
Desarrollador hace push a
maingit push origin main -
Gitea detecta el push y activa el workflow
- El runner recibe el job
-
Runner instala Node.js
- Necesario para que
actions/checkoutfuncione
- Necesario para que
-
Runner hace checkout del código
- Descarga la última versión del repositorio
-
Runner ejecuta
deploy.shen el host- El script se ejecuta con acceso completo a Docker del host
-
deploy.shrealiza el deployment- Actualiza código
- Construye imágenes
- Despliega contenedores
-
Verificación final
- El workflow verifica que los contenedores estén corriendo
Uso Manual del Script
También puedes ejecutar el deployment manualmente:
# Conectarte al servidor
ssh usuario@servidor
# Ir al directorio del proyecto
cd /home/marti/Documentos/Gitea/resistencia
# Ejecutar deployment
./deploy.sh
Esto es útil para:
- Debugging
- Deployments de emergencia
- Probar cambios antes de hacer commit
Comparación con el Ejemplo que Funciona
El ejemplo que compartiste usa runs-on: ubuntu-latest, que es una imagen de GitHub/Gitea con todas las herramientas preinstaladas:
jobs:
build:
runs-on: ubuntu-latest # ← Imagen completa con todo instalado
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4 # ← Node.js ya disponible
- run: mvn clean deploy # ← Maven ya disponible
Tu runner usa runs-on: [production-ready], que es un runner personalizado que:
- ✅ Tiene acceso al Docker del host (vía socket)
- ❌ NO tiene Docker CLI instalado dentro del contenedor
- ❌ NO tiene Node.js preinstalado
- ❌ NO tiene otras herramientas preinstaladas
Por eso necesitamos:
- Instalar Node.js manualmente
- Ejecutar un script en el host (donde Docker SÍ está)
Ventajas del Nuevo Enfoque
- Simplicidad: Un script bash es más fácil de entender que un workflow complejo
- Debugging: Puedes ejecutar
./deploy.shmanualmente para probar - Flexibilidad: Fácil modificar el script sin tocar el workflow
- Portabilidad: El mismo script puede usarse en otros sistemas de CI/CD
- Confiabilidad: Se ejecuta en el host donde sabemos que Docker funciona
Archivos del Sistema
resistencia/
├── .gitea/
│ └── workflows/
│ └── deployment.yml # Workflow simplificado
├── deploy.sh # Script de deployment (NUEVO)
├── docker-compose_prod.yml # Configuración de producción
├── CI-CD-README.md # Documentación general
├── TROUBLESHOOTING-CICD.md # Problemas resueltos
└── monitor-deploy.sh # Script de monitoreo
Próximos Pasos
Ahora que el CI/CD funciona, puedes:
-
Probar el deployment:
git commit --allow-empty -m "test: Probar nuevo CI/CD" git push origin main -
Monitorear en Gitea:
-
Verificar la aplicación:
-
Mejoras futuras:
- Agregar tests antes del deploy
- Implementar rollback automático
- Agregar notificaciones (Discord, email, etc.)
- Backup de base de datos antes de deploy
- Health checks post-deployment
Troubleshooting
Si el workflow falla
- Ver logs en Gitea Actions
- Ejecutar manualmente el script:
cd /home/marti/Documentos/Gitea/resistencia ./deploy.sh - Verificar que Docker funciona en el host:
docker ps docker compose version
Si los contenedores no inician
# Ver logs
docker compose -f docker-compose_prod.yml logs
# Reiniciar servicios
docker compose -f docker-compose_prod.yml restart
# Reconstruir desde cero
docker compose -f docker-compose_prod.yml down
docker compose -f docker-compose_prod.yml up -d --build
Conclusión
Este nuevo enfoque es más simple, más confiable y más fácil de mantener. En lugar de luchar contra las limitaciones del runner, aprovechamos que el runner puede ejecutar scripts en el host donde Docker ya está instalado y funcionando.
¡El CI/CD ahora debería funcionar correctamente! 🎉