name: factuges-rodax services: # --- Base de datos MariaDB --- db: image: mariadb:lts-noble container_name: factuges_rodax_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 - 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_rodax_phpmyadmin restart: unless-stopped environment: PMA_ARBITRARY: 1 PMA_ABSOLUTE_URI: https://factuges.rodax-software.local/phpmyadmin/ PMA_HOST: db PMA_USER: ${DB_USER} PMA_PASSWORD: ${DB_PASS} PMA_VERBOSES: "FactuGES Rodax" MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS} UPLOAD_LIMIT: 64M depends_on: db: condition: service_healthy networks: - internal - edge ports: - "8080:8080" labels: traefik.enable: "true" # /phpmyadmin → phpMyAdmin traefik.http.routers.factuges_rodax_phpmyadmin.rule: "Host(`factuges.rodax-software.local`) && PathPrefix(`/phpmyadmin/`)" traefik.http.routers.factuges_rodax_phpmyadmin.entrypoints: "websecure" traefik.http.routers.factuges_rodax_phpmyadmin.tls: "true" traefik.http.routers.factuges_rodax_phpmyadmin.priority: "110" traefik.http.routers.factuges_rodax_phpmyadmin.service: "factuges_rodax_phpmyadmin" traefik.http.services.factuges_rodax_phpmyadmin.loadbalancer.server.port: "80" # strip /phpmyadmin del path antes de llegar al contenedor traefik.http.middlewares.factuges_rodax_phpmyadmin_strip.stripprefix.prefixes: "/phpmyadmin/" # whitelist a tu IP #traefik.http.middlewares.factuges_rodax_phpmyadmin_ipwhitelist.ipwhitelist.sourcerange: "192.168.0.0/24" # encadenar middlewares traefik.http.routers.factuges_rodax_phpmyadmin.middlewares: "factuges_rodax_phpmyadmin_strip" # --- API (imagen versionada generada por build-api.sh) --- api: image: ${API_IMAGE} container_name: factuges_rodax_api restart: unless-stopped depends_on: db: condition: service_healthy environment: NODE_ENV: production COMPANY: rodax PORT: ${SERVER_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} TEMPLATES_PATH: ${TEMPLATES_PATH} volumes: - ./templates:/repo/apps/server/templates:ro networks: - internal - edge labels: traefik.enable: "true" # /api → backend traefik.http.routers.factuges_rodax_api.rule: "Host(`factuges.rodax-software.local`) && PathPrefix(`/api`)" traefik.http.routers.factuges_rodax_api.entrypoints: "websecure" traefik.http.routers.factuges_rodax_api.tls: "true" traefik.http.routers.factuges_rodax_api.priority: "100" traefik.http.routers.factuges_rodax_api.service: "factuges_rodax_api" # Servicio traefik.http.services.factuges_rodax_api.loadbalancer.server.port: "${API_PORT:-3002}" # --- Web estática (React compilado) --- web: image: nginx:alpine container_name: factuges_rodax_web restart: unless-stopped depends_on: - api environment: VITE_API_SERVER_URL: https://factuges.rodax-software.local/api/v1 volumes: # Build de Vite (en el host) -> Nginx - ./web/latest/dist:/usr/share/nginx/html:ro # Config de Nginx con try_files para SPA - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro networks: - edge labels: traefik.enable: "true" # Router HTTPS traefik.http.routers.factuges_rodax_web.rule: "Host(`factuges.rodax-software.local`)" traefik.http.routers.factuges_rodax_web.entrypoints: "websecure" traefik.http.routers.factuges_rodax_web.tls: "true" # Servicio traefik.http.services.factuges_rodax_web.loadbalancer.server.port: "80" factuges_sync: image: "factuges-sync:rodax-latest" container_name: "factuges_rodax_sync" restart: "no" environment: ENV: "production" LOCAL_TZ: "Europe/Madrid" STATE_PATH: "${STATE_PATH}" 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: - ./volumes/db_sync:/app/rodax networks: edge: name: edge external: true internal: name: factuges_rodax_internal external: false volumes: # Solo declarativo; usamos ruta ./volumes/db_data arriba db_data: