Los hackathons son divertidos pero estresantes, sobre todo cuando tu sitio debe permanecer en línea hasta que termine la evaluación. Aquí tienes una guía completa en pasos reproducibles para despliegues con tiempo mínimo de inactividad, rollback seguro y builds deterministas. Está diseñada para un backend Gradle con Spring Boot, frontend React servido por Nginx, base de datos MySQL, builds Docker multietapa, integración continua con Jenkins y despliegue a un VPS Hostinger sobre Ubuntu usando una estrategia tipo blue green con swap atómico y rollback basado en salud.
Lo que hace única esta aproximación:
Etiquetas deterministas para imágenes con formato YYYYmmddHHMM-gitshort, por ejemplo 202509041530-1a2b3c4
Swap atómico de release: Jenkins despliega en /opt/chattingo/releases/TAG y luego hace un swap atómico a /opt/chattingo/current
Rollback condicionado por healthcheck: si la nueva release no pasa /actuator/health en 60 segundos, se revierte automáticamente
Cache busting en frontend: el build Docker inyecta BUILD_ID único en index.html
Tiempo de inactividad mínimo: los usuarios no ven una app rota
Reproducible y transparente: todos los scripts, configuraciones y Jenkinsfile se almacenan en el repo
Requisitos previos antes de empezar, sustituye los marcadores por tus valores: YOUR_DOCKERHUB_USER, YOUR_DOMAIN, YOUR_VPS_IP, SSH_USER, GIT_BRANCH, JENKINS_CRED_IDS.
Configuración Docker y Compose: a continuación se describen los Dockerfile y la plantilla docker compose. Añade la cadena __BUILD_ID__ dentro de public/index.html para evitar caches obsoletos.
Dockerfile frontend multietapa ejemplo:
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ARG BUILD_ID
RUN if [ -f public/index.html ] ; then sed -i s/__BUILD_ID__/${BUILD_ID}/g public/index.html || true ; fi
RUN npm run build
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.frontend.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD nginx -g daemon off;
Dockerfile backend Gradle multietapa ejemplo:
FROM gradle:8.3-jdk17 AS builder
WORKDIR /app
COPY build.gradle settings.gradle ./
COPY gradle ./gradle
COPY src ./src
RUN gradle clean build -x test --no-daemon
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=5 CMD curl -f https://localhost:8080/actuator/health || exit 1
ENTRYPOINT java -jar /app/app.jar
No es necesario instalar Gradle en Jenkins ya que la compilación ocurre dentro del contenedor builder.
Plantilla docker compose release ejemplo:
version: 3.8
services:
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpass}
MYSQL_DATABASE: ${MYSQL_DATABASE:-chattingo}
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
backend:
image: YOUR_DOCKERHUB_USER/chattingo-backend:PLACEHOLDER_TAG
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/${MYSQL_DATABASE}
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: ${MYSQL_ROOT_PASSWORD}
depends_on:
- db
ports:
- 8080:8080
restart: unless-stopped
frontend:
image: YOUR_DOCKERHUB_USER/chattingo-frontend:PLACEHOLDER_TAG
depends_on:
- backend
ports:
- 3001:80
restart: unless-stopped
volumes:
db_data:
Jenkins se encargará de reemplazar PLACEHOLDER_TAG por la etiqueta única TAG generada en pipeline.
Pipeline Jenkins, flujo resumido: checkout del repo; cálculo de TAG determinista con fecha y git short; build de imagen frontend pasando BUILD_ID; build de imagen backend usando el Dockerfile Gradle; push de ambas imágenes a DockerHub; despliegue al VPS copiando docker compose y ejecutando script de despliegue.
Ejemplo de pasos clave del pipeline:
Generar TAG con fecha y SHA corto
docker build --build-arg BUILD_ID=${TAG} -t IMAGE_PREFIX/chattingo-frontend:${TAG} ./frontend
docker build -t IMAGE_PREFIX/chattingo-backend:${TAG} ./backend
docker login y docker push de ambas imágenes
scp docker-compose.yml al VPS y ejecutar deploy_release.sh con el TAG
Script de despliegue atómico en VPS, guardar como /usr/local/bin/deploy_release.sh y dar permisos de ejecución:
#!/usr/bin/env bash
set -euo pipefail
TAG=$1
RELEASE_DIR=/opt/chattingo/releases/${TAG}
CURRENT_DIR=/opt/chattingo/current
PREV_DIR=/opt/chattingo/previous
TIMEOUT=60
HEALTH_URL=https://YOUR_DOMAIN/actuator/health
if [ ! -d ${RELEASE_DIR} ] ; then exit 2 ; fi
if [ -d ${CURRENT_DIR} ] ; then mv ${CURRENT_DIR} ${PREV_DIR} ; fi
cp -r ${RELEASE_DIR} ${CURRENT_DIR}
cd ${CURRENT_DIR}
docker compose up -d --remove-orphans
SECONDS=0
until curl -fsS ${HEALTH_URL} > /dev/null ; do sleep 5 ; if [ $SECONDS -ge $TIMEOUT ] ; then docker compose down || true ; if [ -d ${PREV_DIR} ] ; then mv ${PREV_DIR} ${CURRENT_DIR} ; cd ${CURRENT_DIR} ; docker compose up -d ; fi ; exit 3 ; fi ; done
rm -rf ${PREV_DIR}
Este flujo garantiza rollback instantáneo si la nueva versión no pasa el healthcheck en el tiempo definido.
Configuración Nginx reverso en /etc/nginx/sites-available/chattingo ejemplo:
server { listen 80 ; server_name YOUR_DOMAIN ; return 301 https:// $host$request_uri ; }
server { listen 443 ssl ; server_name YOUR_DOMAIN ; ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem ; ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem ; location / { proxy_pass https://127.0.0.1:3001/ ; } location /api/ { proxy_pass https://127.0.0.1:8080/api/ ; } }
Luego crear enlace simbólico a sites-enabled, probar configuración y recargar nginx.
Buenas prácticas y recomendaciones: usar SSL con LetsEncrypt, almacenar secretos en Jenkins Credentials, usar health endpoints robustos, mantener volúmenes de datos persistentes y automatizar backups de MySQL, custodiar credenciales DockerHub y acceso SSH, y versionar todos los scripts de despliegue en el repositorio para trazabilidad.
Sobre Q2BSTUDIO: somos una empresa de desarrollo de software especializada en aplicaciones a medida y software a medida, con experiencia en inteligencia artificial, ciberseguridad y servicios cloud. Si buscas desarrollar productos robustos y escalables, podemos ayudarte desde la arquitectura hasta la puesta en producción. Conectamos la ingeniería DevOps con soluciones a medida, incluyendo servicios de desarrollo de aplicaciones y software a medida y migraciones o despliegues en la nube con servicios cloud AWS y Azure.
Palabras clave incorporadas naturalmente: aplicaciones a medida, software a medida, inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio, ia para empresas, agentes IA, power bi. Ofrecemos también servicios de Business Intelligence y Power BI, automatización de procesos, agentes IA y consultoría en ciberseguridad para garantizar despliegues seguros y resilientes.
Si necesitas que preparemos los archivos listos para clonar en tu repositorio y adaptar los scripts a tu infraestructura, contacta con Q2BSTUDIO y te acompañamos en el diseño de pipelines, seguridad y operación en producción.