Desarrollo de Servicios – Backend¶
Patrones recomendados (basados en proyectos en curso) para microservicios backend.
Framework¶
NestJS + TypeScript.
APIs¶
REST/GraphQL documentadas con OpenAPI/Swagger; versionado y contratos claros.
Seguridad¶
Tokens emitidos por IDR; headers secretos cuando aplique (ej. api_secret en GDE Gateway); rate limiting y logs.
Datos¶
PostgreSQL para datos estructurales; MongoDB u otros motores según uso (ej. fichadas en concentrador).
Ejemplos de referencia¶
GDE Gateway¶
Proxy SOAP seguro; validación de api_secret; variables GATEWAY_PORT, GDE_URL, API_SECRET.
Concentrador de Fichadas¶
API REST con admin secret + API keys; PostgreSQL + MongoDB; documentación Swagger.
Entrega¶
Contenedores Docker; docker-compose para dev; CI/CD con build y push de imágenes.
Operación¶
Health checks, logs estructurados, métricas; exportar docs en /api/docs u endpoint equivalente.
Estructura de un microservicio¶
microservicio/
├── src/ # Código fuente
├── docker/
│ ├── dockerfile.dev # Build para desarrollo (con devDependencies)
│ └── dockerfile.prod # Build multi-stage para producción
├── Makefile # Targets: dev-img, prod-img, push-*
├── package.json # Dependencias (o equivalente en otro lenguaje)
├── env.example # Variables de entorno documentadas
├── README.md
├── .gitignore
└── .dockerignore
Variables de ambiente¶
- Todas las configuraciones vienen del ambiente (nunca hardcodear).
- Cada servicio mantiene su
env.exampledocumentando las variables que usa. - El dev-env centraliza todas las variables en
config/env.example. .envnunca va a git; se genera desdeenv.exampley se ajusta por ambiente.
Dockerfiles multi-stage¶
dockerfile.dev¶
Imagen ligera para desarrollo, con CLI y hot reload:
FROM node:24
WORKDIR /usr/src/app
RUN npm install -g @nestjs/cli
CMD ["nest","start","--watch"]
dockerfile.prod¶
Usa la imagen dev como base y genera una imagen productiva inmutable:
ARG IMAGE
FROM ${IMAGE}-dev:latest as build
COPY . /usr/src/app
RUN nest build
FROM ${IMAGE}-dev:latest
COPY node_modules /usr/src/app/
COPY --from=build /usr/src/app/dist /usr/src/app/
CMD ["node", "main.js"]
Makefile de imágenes¶
El Makefile del servicio automatiza construcción y push de imágenes dev y prod:
.PHONY: dev-img push-dev-img prod-img push-prod-img
dev-img:
ifndef IMAGE_NAME
$(error Uso: make dev-img IMAGE_NAME=registry.io/proyecto/servicio)
endif
docker buildx build --tag $(IMAGE_NAME)-dev:latest -f docker/dockerfile.dev .
push-dev-img:
ifndef IMAGE_NAME
$(error Uso: make push-dev-img IMAGE_NAME=registry.io/proyecto/servicio)
endif
docker push $(IMAGE_NAME)-dev:latest
prod-img:
ifndef IMAGE_NAME
$(error Uso: make prod-img IMAGE_NAME=registry.io/proyecto/servicio VERSION=x.y.z)
endif
ifndef VERSION
$(error VERSION es requerida: make prod-img IMAGE_NAME=... VERSION=x.y.z)
endif
npm install --omit=dev --prefer-offline --no-audit --fund false
docker buildx build --tag $(IMAGE_NAME):$(VERSION) -f docker/dockerfile.prod .
push-prod-img:
ifndef IMAGE_NAME
$(error Uso: make push-prod-img IMAGE_NAME=registry.io/proyecto/servicio VERSION=x.y.z)
endif
ifndef VERSION
$(error VERSION es requerida: make push-prod-img IMAGE_NAME=... VERSION=x.y.z)
endif
docker push $(IMAGE_NAME):$(VERSION)
Uso típico:
# Desarrollo manual
make dev-img IMAGE_NAME=registry.io/proyecto/backend
make push-dev-img IMAGE_NAME=registry.io/proyecto/backend
# Producción desde CI/CD
make prod-img IMAGE_NAME=registry.io/proyecto/backend VERSION=1.0.0
make push-prod-img IMAGE_NAME=registry.io/proyecto/backend VERSION=1.0.0
Versionado semántico y CI/CD¶
Esquema sugerido:
v1.0.0 # Primera versión (MAJOR.MINOR.PATCH)
v1.0.1 # Cada merge a dev (PATCH++)
v1.1.0 # Cada despliegue productivo (MINOR++, PATCH=0)
v2.0.0 # Cambios incompatibles (MAJOR++)
``]
En GitLab, el pipeline puede:
1. Calcular la próxima versión (leyendo tags).
2. Crear un nuevo tag.
3. Construir y pushear la imagen `servicio:<version>`.
---
## Health check obligatorio
Todos los servicios deben exponer `/health` y usarse en Docker/K8s para healthchecks.
Ejemplo con NestJS:
```typescript
@Controller('health')
export class HealthController {
@Get()
health() {
return { ok: true, timestamp: new Date().toISOString() };
}
}