2025-11-30 21:30:57 +00:00
|
|
|
services:
|
|
|
|
|
# --- Base de datos MariaDB ---
|
|
|
|
|
db:
|
|
|
|
|
image: mariadb:lts-noble
|
|
|
|
|
container_name: factuges_acana_db
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
environment:
|
|
|
|
|
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASS}
|
|
|
|
|
MARIADB_USER: ${DB_USER}
|
|
|
|
|
MARIADB_PASSWORD: ${DB_PASS}
|
|
|
|
|
MARIADB_DATABASE: ${DB_NAME}
|
|
|
|
|
volumes:
|
|
|
|
|
- ./volumes/db_data:/var/lib/mysql
|
|
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
healthcheck:
|
|
|
|
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
|
|
|
|
interval: 20s
|
|
|
|
|
timeout: 5s
|
|
|
|
|
retries: 10
|
|
|
|
|
|
|
|
|
|
# --- phpMyAdmin (solo accesible por Traefik + whitelist IP) ---
|
|
|
|
|
phpmyadmin:
|
2025-11-30 21:32:02 +00:00
|
|
|
image: phpmyadmin/phpmyadmin:latest
|
2025-11-30 21:30:57 +00:00
|
|
|
container_name: factuges_acana_phpmyadmin
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
environment:
|
2025-11-30 21:32:02 +00:00
|
|
|
PMA_ARBITRARY: 1
|
|
|
|
|
PMA_ABSOLUTE_URI: https://acana.factuges.app/phpmyadmin/
|
2025-11-30 21:30:57 +00:00
|
|
|
PMA_HOST: db
|
|
|
|
|
PMA_USER: ${DB_USER}
|
|
|
|
|
PMA_PASSWORD: ${DB_PASS}
|
|
|
|
|
PMA_VERBOSES: "FactuGES Acana"
|
|
|
|
|
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
|
|
|
|
|
UPLOAD_LIMIT: 64M
|
|
|
|
|
depends_on:
|
|
|
|
|
- db
|
|
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
- edge
|
|
|
|
|
labels:
|
|
|
|
|
traefik.enable: "true"
|
|
|
|
|
# /phpmyadmin → phpMyAdmin
|
2025-11-30 21:32:02 +00:00
|
|
|
traefik.http.routers.factuges_acana_phpmyadmin.rule: "Host(`${DOMAIN}`) && PathPrefix(`/phpmyadmin/`)"
|
2025-11-30 21:30:57 +00:00
|
|
|
traefik.http.routers.factuges_acana_phpmyadmin.entrypoints: websecure
|
2025-11-30 21:32:02 +00:00
|
|
|
#traefik.http.routers.factuges_acana_phpmyadmin.tls: true
|
2025-11-30 21:30:57 +00:00
|
|
|
traefik.http.routers.factuges_acana_phpmyadmin.tls.certresolver: cloudflare-dns
|
|
|
|
|
traefik.http.routers.factuges_acana_phpmyadmin.priority: "110"
|
|
|
|
|
traefik.http.routers.factuges_acana_phpmyadmin.service: factuges_acana_phpmyadmin
|
|
|
|
|
traefik.http.services.factuges_acana_phpmyadmin.loadbalancer.server.port: "80"
|
|
|
|
|
|
|
|
|
|
# strip /phpmyadmin del path antes de llegar al contenedor
|
2025-11-30 21:32:02 +00:00
|
|
|
traefik.http.middlewares.factuges_acana_phpmyadmin_strip.stripprefix.prefixes: "/phpmyadmin/"
|
2025-11-30 21:30:57 +00:00
|
|
|
|
|
|
|
|
# whitelist a tu IP
|
|
|
|
|
traefik.http.middlewares.factuges_acana_phpmyadmin_ipwhitelist.ipwhitelist.sourcerange: "79.116.183.41/32"
|
|
|
|
|
|
|
|
|
|
# encadenar middlewares
|
|
|
|
|
traefik.http.routers.factuges_acana_phpmyadmin.middlewares: "factuges_acana_phpmyadmin_strip,factuges_acana_phpmyadmin_ipwhitelist"
|
|
|
|
|
|
|
|
|
|
# --- API Node.js ---
|
|
|
|
|
api:
|
2025-11-30 21:32:02 +00:00
|
|
|
image: ${API_IMAGE}
|
2025-11-30 21:30:57 +00:00
|
|
|
container_name: factuges_acana_api
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
depends_on:
|
|
|
|
|
db:
|
|
|
|
|
condition: service_healthy
|
|
|
|
|
environment:
|
|
|
|
|
NODE_ENV: production
|
|
|
|
|
COMPANY: acana
|
|
|
|
|
PORT: ${API_PORT:-3002}
|
|
|
|
|
DB_DIALECT: "mysql"
|
|
|
|
|
DB_HOST: "db"
|
|
|
|
|
DB_PORT: ${DB_PORT}
|
|
|
|
|
DB_NAME: ${DB_NAME}
|
|
|
|
|
DB_USER: ${DB_USER}
|
|
|
|
|
DB_PASS: ${DB_PASS}
|
|
|
|
|
FRONTEND_URL: ${FRONTEND_URL}
|
2025-12-01 11:38:42 +00:00
|
|
|
TEMPLATES_PATH: ${TEMPLATES_PATH}
|
|
|
|
|
volumes:
|
|
|
|
|
- ./templates:/repo/apps/server/templates:ro
|
2025-11-30 21:30:57 +00:00
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
- edge
|
|
|
|
|
labels:
|
|
|
|
|
traefik.enable: "true"
|
|
|
|
|
# /api → backend
|
|
|
|
|
traefik.http.routers.factuges_acana_api.rule: Host(`${DOMAIN}`) && PathPrefix(`/api`)
|
|
|
|
|
traefik.http.routers.factuges_acana_api.entrypoints: websecure
|
|
|
|
|
traefik.http.routers.factuges_acana_api.tls.certresolver: cloudflare-dns
|
|
|
|
|
|
|
|
|
|
traefik.http.routers.factuges_acana_api.priority: "100"
|
|
|
|
|
traefik.http.routers.factuges_acana_api.service: factuges_acana_api
|
|
|
|
|
|
|
|
|
|
# Servicio
|
|
|
|
|
traefik.http.services.factuges_acana_api.loadbalancer.server.port: "${API_PORT:-3002}"
|
|
|
|
|
|
|
|
|
|
# --- Web estática Vite (nginx) ---
|
|
|
|
|
web:
|
|
|
|
|
image: nginx:alpine
|
|
|
|
|
container_name: factuges_acana_web
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
depends_on:
|
|
|
|
|
- api
|
|
|
|
|
environment:
|
|
|
|
|
VITE_API_SERVER_URL: ${DOMAIN}/api
|
|
|
|
|
volumes:
|
|
|
|
|
- ./web/public:/usr/share/nginx/html:ro
|
|
|
|
|
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
|
|
|
|
networks:
|
|
|
|
|
- edge
|
|
|
|
|
labels:
|
|
|
|
|
traefik.enable: "true"
|
|
|
|
|
# / → frontend
|
|
|
|
|
traefik.http.routers.factuges_acana_web.rule: Host(`${DOMAIN}`) && PathPrefix(`/`)
|
|
|
|
|
traefik.http.routers.factuges_acana_web.entrypoints: websecure
|
|
|
|
|
traefik.http.routers.factuges_acana_web.tls.certresolver: cloudflare-dns
|
|
|
|
|
|
|
|
|
|
# prioridad más baja para que /api y /phpmyadmin ganen
|
|
|
|
|
traefik.http.routers.factuges_acana_web.priority: "1"
|
|
|
|
|
traefik.http.routers.factuges_acana_web.service: factuges_acana_web
|
|
|
|
|
traefik.http.services.factuges_acana_web.loadbalancer.server.port: "80"
|
|
|
|
|
|
2025-11-30 21:32:02 +00:00
|
|
|
|
|
|
|
|
factuges_sync:
|
2025-12-01 08:59:59 +00:00
|
|
|
image: "factuges-sync:acana-latest"
|
|
|
|
|
container_name: "factuges-sync-acana"
|
2025-11-30 21:32:02 +00:00
|
|
|
restart: "no"
|
|
|
|
|
environment:
|
|
|
|
|
ENV: "production"
|
|
|
|
|
LOCAL_TZ: "Europe/Madrid"
|
2025-12-01 08:59:59 +00:00
|
|
|
STATE_PATH: "${STATE_PATH}"
|
2025-11-30 21:32:02 +00:00
|
|
|
|
|
|
|
|
FACTUGES_HOST: "${FACTUGES_HOST}"
|
|
|
|
|
FACTUGES_PORT: "${FACTUGES_PORT}"
|
|
|
|
|
FACTUGES_DATABASE: "${FACTUGES_DATABASE}"
|
|
|
|
|
FACTUGES_USER: "${FACTUGES_USER}"
|
|
|
|
|
FACTUGES_PASSWORD: "${FACTUGES_PASSWORD}"
|
|
|
|
|
|
|
|
|
|
FWEB_MYSQL_HOST: "db"
|
|
|
|
|
FWEB_MYSQL_PORT: "${DB_PORT}"
|
|
|
|
|
FWEB_MYSQL_DATABASE: "${DB_NAME}"
|
|
|
|
|
FWEB_MYSQL_USER: "${DB_USER}"
|
|
|
|
|
FWEB_MYSQL_PASSWORD: "${DB_PASS}"
|
|
|
|
|
|
|
|
|
|
CTE_COMPANY_ID: "${CTE_COMPANY_ID}"
|
|
|
|
|
CTE_SERIE: "${CTE_SERIE}"
|
|
|
|
|
CTE_STATUS_INVOICE: "${CTE_STATUS_INVOICE}"
|
|
|
|
|
CTE_IS_PROFORMA: "${CTE_IS_PROFORMA}"
|
|
|
|
|
CTE_STATUS_VERIFACTU: "${CTE_STATUS_VERIFACTU}"
|
|
|
|
|
CTE_LANGUAGE_CODE: "${CTE_LANGUAGE_CODE}"
|
|
|
|
|
CTE_COUNTRY_CODE: "${CTE_COUNTRY_CODE}"
|
|
|
|
|
CTE_IS_COMPANY: "${CTE_IS_COMPANY}"
|
|
|
|
|
CTE_SYNC_RESULT_OK: "${CTE_SYNC_RESULT_OK}"
|
|
|
|
|
CTE_SYNC_RESULT_FAIL: "${CTE_SYNC_RESULT_FAIL}"
|
|
|
|
|
|
|
|
|
|
VERIFACTU_API_KEY: "${VERIFACTU_API_KEY}"
|
|
|
|
|
VERIFACTU_BASE_URL: "${VERIFACTU_BASE_URL}"
|
|
|
|
|
VERIFACTU_NIFS_API_KEY: "${VERIFACTU_NIFS_API_KEY}"
|
|
|
|
|
depends_on:
|
|
|
|
|
db:
|
|
|
|
|
condition: service_healthy
|
|
|
|
|
networks:
|
|
|
|
|
- internal
|
|
|
|
|
- edge
|
|
|
|
|
volumes:
|
2025-12-01 08:59:59 +00:00
|
|
|
- ./volumes/db_sync:/app/state
|
2025-11-30 21:32:02 +00:00
|
|
|
|
2025-11-30 21:30:57 +00:00
|
|
|
networks:
|
|
|
|
|
edge:
|
|
|
|
|
name: edge
|
|
|
|
|
external: true
|
|
|
|
|
internal:
|
|
|
|
|
name: factuges_acana_internal
|
|
|
|
|
external: false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
volumes:
|
|
|
|
|
# Solo declarativo; usamos ruta ./volumes/db_data arriba
|
|
|
|
|
db_data:
|