2025-11-27 19:07:30 +00:00
|
|
|
|
|
|
|
|
# ======================================================
|
|
|
|
|
# STACK POR COMPAÑÍA
|
|
|
|
|
# - API Node.js
|
|
|
|
|
# - Web React (Nginx)
|
|
|
|
|
# - MariaDB
|
|
|
|
|
# - Integrado con Traefik
|
|
|
|
|
# ======================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
services:
|
|
|
|
|
# --- Base de datos MariaDB ---
|
|
|
|
|
db:
|
|
|
|
|
image: mariadb:lts-noble
|
|
|
|
|
container_name: factuges_${COMPANY}_db
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
environment:
|
|
|
|
|
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASS}
|
|
|
|
|
MARIADB_USER: ${DB_USER}
|
|
|
|
|
MARIADB_PASSWORD: ${DB_PASS}
|
|
|
|
|
MARIADB_DATABASE: ${DB_NAME}
|
|
|
|
|
volumes:
|
|
|
|
|
- /opt/factuges/${COMPANY}/volumes/db_data:/var/lib/mysql
|
|
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
- edge
|
|
|
|
|
ports:
|
|
|
|
|
- 3306:3306
|
|
|
|
|
healthcheck:
|
|
|
|
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
|
|
|
|
interval: 20s
|
|
|
|
|
timeout: 5s
|
|
|
|
|
retries: 10
|
|
|
|
|
|
|
|
|
|
phpmyadmin:
|
|
|
|
|
image: phpmyadmin/phpmyadmin
|
|
|
|
|
container_name: factuges_${COMPANY}_phpmyadmin
|
|
|
|
|
restart: always
|
|
|
|
|
environment:
|
|
|
|
|
PMA_HOST: db
|
|
|
|
|
PMA_USER: ${DB_USER}
|
|
|
|
|
PMA_PASSWORD: ${DB_PASS}
|
|
|
|
|
PMA_VERBOSES: "FactuGES Rodax"
|
|
|
|
|
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
|
|
|
|
|
UPLOAD_LIMIT: 64M
|
|
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
- edge
|
|
|
|
|
depends_on:
|
|
|
|
|
- db
|
|
|
|
|
ports:
|
|
|
|
|
- 8080:80
|
|
|
|
|
labels:
|
|
|
|
|
traefik.enable: "true"
|
|
|
|
|
# Router
|
|
|
|
|
traefik.http.routers.${COMPANY}-phpmyadmin.rule: Host(`${PMA_DOMAIN}`)
|
|
|
|
|
traefik.http.routers.${COMPANY}-phpmyadmin.entrypoints: websecure
|
|
|
|
|
traefik.http.routers.${COMPANY}-phpmyadmin.tls.certresolver: cfresolver
|
|
|
|
|
# Servicio
|
|
|
|
|
traefik.http.services.${COMPANY}-phpmyadmin.loadbalancer.server.port: "80"
|
|
|
|
|
# Middleware: whitelist por IP
|
|
|
|
|
traefik.http.routers.${COMPANY}-phpmyadmin.middlewares: "${COMPANY}-phpmyadmin-ipwhitelist@docker"
|
|
|
|
|
traefik.http.middlewares.${COMPANY}-phpmyadmin-ipwhitelist.ipwhitelist.sourcerange: "79.116.183.41/32"
|
|
|
|
|
|
|
|
|
|
# --- API (imagen versionada generada por build-factuges.sh) ---
|
|
|
|
|
api:
|
|
|
|
|
image: ${API_IMAGE}
|
|
|
|
|
container_name: factuges_${COMPANY}_api
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
depends_on:
|
|
|
|
|
db:
|
|
|
|
|
condition: service_healthy
|
|
|
|
|
environment:
|
|
|
|
|
NODE_ENV: production
|
|
|
|
|
COMPANY: ${COMPANY}
|
2025-12-15 18:21:09 +00:00
|
|
|
PORT: ${API_PORT:-3002}
|
2025-11-27 19:07:30 +00:00
|
|
|
DB_DIALECT: "mysql"
|
|
|
|
|
DB_HOST: "db"
|
|
|
|
|
DB_PORT: ${DB_PORT}
|
|
|
|
|
DB_NAME: ${DB_NAME}
|
|
|
|
|
DB_USER: ${DB_USER}
|
|
|
|
|
DB_PASSWORD: ${DB_PASS}
|
|
|
|
|
FRONTEND_URL: ${FRONTEND_URL}
|
|
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
- edge
|
|
|
|
|
ports:
|
2025-12-15 18:21:09 +00:00
|
|
|
- ${API_PORT:-3002}:${API_PORT:-3002}
|
2025-11-27 19:07:30 +00:00
|
|
|
labels:
|
|
|
|
|
traefik.enable: "true"
|
|
|
|
|
# Router
|
|
|
|
|
traefik.http.routers.${COMPANY}-api.rule: Host(`${API_DOMAIN}`)
|
|
|
|
|
traefik.http.routers.${COMPANY}-api.entrypoints: websecure
|
|
|
|
|
traefik.http.routers.${COMPANY}-api.tls.certresolver: cfresolver
|
|
|
|
|
# Servicio
|
2025-12-15 18:21:09 +00:00
|
|
|
traefik.http.services.${COMPANY}-api.loadbalancer.server.port: "${API_PORT:-3002}"
|
2025-11-27 19:07:30 +00:00
|
|
|
|
|
|
|
|
# --- Web estática (React compilado por build-factuges.sh) ---
|
|
|
|
|
web:
|
|
|
|
|
container_name: caddy
|
|
|
|
|
image: caddy:alpine
|
|
|
|
|
volumes:
|
|
|
|
|
- /opt/factuges/${COMPANY}/Caddyfile:/etc/caddy/Caddyfile # Monta el archivo de configuración
|
|
|
|
|
- caddy_data:/data # Almacena los certificados en este volumen
|
|
|
|
|
- caddy_config:/config # Configuración de Caddy
|
|
|
|
|
- /opt/factuges/${COMPANY}/web/latest/dist/:/srv
|
|
|
|
|
ports:
|
|
|
|
|
- 81:80 # Puerto HTTP (Caddy lo redirige automáticamente a HTTPS)
|
|
|
|
|
- 444:443 # Puerto HTTPS
|
|
|
|
|
- 13001:13001 # reverse proxy al backend
|
|
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
- edge
|
|
|
|
|
restart: on-failure
|
|
|
|
|
depends_on:
|
|
|
|
|
- api
|
|
|
|
|
labels:
|
|
|
|
|
traefik.enable: "true"
|
|
|
|
|
traefik.http.routers.factuges_rodax_web.rule: Host(`${DOMAIN}`)
|
|
|
|
|
traefik.http.routers.factuges_rodax_web.entrypoints: web
|
|
|
|
|
traefik.http.services.factuges_rodax_web.loadbalancer.server.port: "444"
|
|
|
|
|
|
|
|
|
|
networks:
|
|
|
|
|
edge:
|
|
|
|
|
external: true # red pública manejada por Traefik
|
|
|
|
|
internal:
|
|
|
|
|
driver: bridge # red privada de la compañía
|
|
|
|
|
|
|
|
|
|
volumes:
|
|
|
|
|
db_data:
|
|
|
|
|
caddy_data:
|
|
|
|
|
caddy_config:
|
|
|
|
|
|