services: # ================= INFRA ================= mongodb: image: mongo:${IMAGEM_LATEST} profiles: ["infra"] ports: - "${MONGO_PORT}:27017" volumes: - mongodb_data:/data/db networks: - app-network healthcheck: test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet interval: 10s timeout: 5s retries: 5 consul: image: hashicorp/consul:latest profiles: ["infra"] ports: - "${CONSUL_HTTP_PORT}:8500" - "${CONSUL_DNS_PORT}:8600/udp" command: "agent -server -bootstrap -ui -client=0.0.0.0" networks: - app-network healthcheck: test: ["CMD", "consul", "members"] interval: 10s timeout: 5s retries: 5 postgres: image: postgres:16-alpine profiles: ["infra"] ports: - "${POSTGRES_PORT}:5432" environment: - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_DB=${POSTGRES_DB} volumes: - postgres_data:/var/lib/postgresql/data networks: - app-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 rabbitmq: image: rabbitmq:4-management-alpine profiles: ["infra"] ports: - "${RABBITMQ_PORT}:5672" - "${RABBITMQ_MANAGEMENT_PORT}:15672" environment: - RABBITMQ_DEFAULT_USER=${RABBITMQ_USER} - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD} - RABBITMQ_DEFAULT_VHOST=${RABBITMQ_VHOST} volumes: - rabbitmq_data:/var/lib/rabbitmq - ./rabbitmq/definitions.json:/etc/rabbitmq/definitions.json:ro - ./rabbitmq/definitions.conf:/etc/rabbitmq/conf.d/20-definitions.conf:ro networks: - app-network healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 10s timeout: 5s retries: 5 # ================= BACKEND ================= suite-api: image: ${DOCKER_REPO}/suite-api:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] ports: - "${BACKEND_SUITE_API_INTERNAL_PORT}:${BACKEND_SUITE_API_INTERNAL_PORT}" environment: - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT} - MONGODB_CONNECTION_STRING=${MONGODB_CONNECTION_STRING} - MONGODB_DATABASE=${MONGODB_DATABASE} - SYSTEM_BASE_CONN=${SYSTEM_BASE_CONN} - FRONTEND_CONN=${INTERNAL_HOST}:${FRONTEND_SUITE_APP_INTERNAL_PORT} - ConsulSettings__Address=http://consul:8500 - Messaging__RabbitMQ__Host=rabbitmq - Messaging__RabbitMQ__Port=5672 - Messaging__RabbitMQ__VirtualHost=${RABBITMQ_SUITE_VHOST} - Messaging__RabbitMQ__Username=${RABBITMQ_SUITE_OWNER_USER} - Messaging__RabbitMQ__Password=${RABBITMQ_SUITE_OWNER_PASSWORD} - Messaging__RabbitMQ__Messaging__ServiceName=suite - Messaging__RabbitMQ__Connections__users__Host=rabbitmq - Messaging__RabbitMQ__Connections__users__Port=5672 - Messaging__RabbitMQ__Connections__users__VirtualHost=${RABBITMQ_USERS_VHOST} - Messaging__RabbitMQ__Connections__users__Username=${RABBITMQ_USERS_WRITER_USER} - Messaging__RabbitMQ__Connections__users__Password=${RABBITMQ_USERS_WRITER_PASSWORD} - KEEPALIVE_ATTENDANCE_SYSTEM_BACKEND_HOST=${KEEPALIVE_ATTENDANCE_SYSTEM_BACKEND_HOST} - KEEPALIVE_ATTENDANCE_SYSTEM_FRONTEND_HOST=${KEEPALIVE_ATTENDANCE_SYSTEM_FRONTEND_HOST} - KEEPALIVE_REPORTS_BACKEND_HOST=${KEEPALIVE_REPORTS_BACKEND_HOST} - KEEPALIVE_REPORTS_FRONTEND_HOST=${KEEPALIVE_REPORTS_FRONTEND_HOST} - KEEPALIVE_USERS_BACKEND_HOST=${KEEPALIVE_USERS_BACKEND_HOST} - KEEPALIVE_USERS_FRONTEND_HOST=${KEEPALIVE_USERS_FRONTEND_HOST} depends_on: consul: condition: service_healthy rabbitmq: condition: service_healthy networks: - app-network users-api: image: ${DOCKER_REPO}/sca-users-api:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] ports: - "${BACKEND_USERS_API_INTERNAL_PORT}:${BACKEND_USERS_API_INTERNAL_PORT}" environment: - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT} - ConnectionStrings__UsersDb=Host=postgres;Port=5432;Database=seventh_users;Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD} - MongoDbSettings__ConnectionString=mongodb://mongodb:27017 - ConsulSettings__Address=http://consul:8500 - ServiceRegistrationSettings__Host=users-api - ServiceRegistrationSettings__Port=${BACKEND_USERS_API_INTERNAL_PORT} - Messaging__RabbitMQ__Host=rabbitmq - Messaging__RabbitMQ__Port=5672 - Messaging__RabbitMQ__VirtualHost=${RABBITMQ_USERS_VHOST} - Messaging__RabbitMQ__Username=${RABBITMQ_USERS_OWNER_USER} - Messaging__RabbitMQ__Password=${RABBITMQ_USERS_OWNER_PASSWORD} - Messaging__RabbitMQ__Messaging__ServiceName=users - Messaging__RabbitMQ__Connections__suite__Host=rabbitmq - Messaging__RabbitMQ__Connections__suite__Port=5672 - Messaging__RabbitMQ__Connections__suite__VirtualHost=${RABBITMQ_SUITE_VHOST} - Messaging__RabbitMQ__Connections__suite__Username=${RABBITMQ_SUITE_WRITER_USER} - Messaging__RabbitMQ__Connections__suite__Password=${RABBITMQ_SUITE_WRITER_PASSWORD} depends_on: postgres: condition: service_healthy mongodb: condition: service_healthy consul: condition: service_healthy rabbitmq: condition: service_healthy networks: - app-network reports-api: image: ${DOCKER_REPO}/sca-reports-api:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] ports: - "${BACKEND_REPORTS_API_INTERNAL_PORT}:${BACKEND_REPORTS_API_INTERNAL_PORT}" environment: - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT} - MONGODB_CONNECTION_STRING=${MONGODB_CONNECTION_STRING} - MONGODB_DATABASE=${MONGODB_DATABASE} - SystemBaseConn=${SYSTEM_BASE_CONN} - FRONTEND_CONN=${INTERNAL_HOST}:${FRONTEND_REPORTS_APP_INTERNAL_PORT} - KEEPALIVE_ATTENDANCE_SYSTEM_BACKEND_HOST=${KEEPALIVE_ATTENDANCE_SYSTEM_BACKEND_HOST} - KEEPALIVE_ATTENDANCE_SYSTEM_FRONTEND_HOST=${KEEPALIVE_ATTENDANCE_SYSTEM_FRONTEND_HOST} - KEEPALIVE_REPORTS_BACKEND_HOST=${KEEPALIVE_REPORTS_BACKEND_HOST} - KEEPALIVE_REPORTS_FRONTEND_HOST=${KEEPALIVE_REPORTS_FRONTEND_HOST} networks: - app-network attendancesystem-api: image: ${DOCKER_REPO}/backend-attendance-system-api:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] ports: - "${BACKEND_ATTENDANCESYSTEM_API_INTERNAL_PORT}:${BACKEND_ATTENDANCESYSTEM_API_INTERNAL_PORT}" environment: - SYSBASE_URL=${SYSTEM_BASE_CONN} - SystemBaseConn=${SYSTEM_BASE_CONN} - FrotendConn=${EXTERNAL_HOST}:${FRONTEND_ATTENDANCESYSTEM_APP_EXTERNAL_PORT} networks: - app-network # ================= FRONTEND ================= config-generator: image: alpine:${IMAGEM_LATEST} profiles: ["app"] environment: - BACKEND_HOST=${SYSTEM_BASE_HOST} - BACKEND_PORT=${SYSTEM_BASE_PORT} - FRONTEND_SUITE_URL=${EXTERNAL_HOST}:${FRONTEND_SUITE_APP_EXTERNAL_PORT} - FRONTEND_ATTENDANCE_URL=${EXTERNAL_HOST}:${FRONTEND_ATTENDANCESYSTEM_APP_EXTERNAL_PORT} - FRONTEND_ACCOUNT_URL=${EXTERNAL_HOST}:${FRONTEND_ACCOUNT_APP_EXTERNAL_PORT} - FRONTEND_PEOPLE_URL=${EXTERNAL_HOST}:${FRONTEND_PEOPLE_APP_EXTERNAL_PORT} - BACKEND_SUITE_API_URL=${EXTERNAL_HOST}:${BACKEND_SUITE_API_EXTERNAL_PORT} - BACKEND_ATTENDANCE_API_URL=${EXTERNAL_HOST}:${BACKEND_ATTENDANCESYSTEM_API_EXTERNAL_PORT} - BACKEND_PEOPLE_API_URL=${EXTERNAL_HOST}:${BACKEND_PEOPLE_API_EXTERNAL_PORT} - BACKEND_ACCOUNT_API_URL=${EXTERNAL_HOST}:${BACKEND_ACCOUNT_API_EXTERNAL_PORT} - BACKEND_REPORTS_API_URL=${EXTERNAL_HOST}:${BACKEND_REPORTS_API_EXTERNAL_PORT} - BACKEND_USERS_API_URL=${EXTERNAL_HOST}:${BACKEND_USERS_API_EXTERNAL_PORT} - BACKEND_TENANTS_API_URL=${EXTERNAL_HOST}:${BACKEND_TENANTS_API_EXTERNAL_PORT} - FRONTEND_REPORTS_URL=${EXTERNAL_HOST}:${FRONTEND_REPORTS_APP_EXTERNAL_PORT} - FRONTEND_USERS_URL=${EXTERNAL_HOST}:${FRONTEND_USERS_APP_EXTERNAL_PORT} - FRONTEND_TENANTS_URL=${EXTERNAL_HOST}:${FRONTEND_TENANTS_APP_EXTERNAL_PORT} command: > sh -c "apk add --no-cache gettext && envsubst < /config.template.json > /output/config.json && echo '✅ Config gerado com sucesso' && chmod 644 /output/config.json" volumes: - ./config.template.json:/config.template.json - config-volume:/output restart: "no" attendancesystem-app: image: ${DOCKER_REPO}/attendancesystem-frontend:${IMAGEM_RELEASE} profiles: ["app"] volumes: - config-volume:/config-inject:ro entrypoint: > sh -c "cp /config-inject/config.json /usr/share/nginx/html/config.json && nginx -g 'daemon off;'" ports: - "${FRONTEND_ATTENDANCESYSTEM_APP_INTERNAL_PORT}:${NGINX_DEFAULT_PORT}" networks: - app-network depends_on: config-generator: condition: service_completed_successfully reports-app: image: ${DOCKER_REPO}/reports-app:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] volumes: - config-volume:/config-inject:ro entrypoint: > sh -c "cp /config-inject/config.json /usr/share/nginx/html/config.json && nginx -g 'daemon off;'" ports: - "${FRONTEND_REPORTS_APP_INTERNAL_PORT}:${NGINX_DEFAULT_PORT}" networks: - app-network depends_on: config-generator: condition: service_completed_successfully users-app: image: ${DOCKER_REPO}/users-app:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] volumes: - config-volume:/config-inject:ro entrypoint: > sh -c "cp /config-inject/config.json /usr/share/nginx/html/config.json && nginx -g 'daemon off;'" ports: - "${FRONTEND_USERS_APP_INTERNAL_PORT}:${NGINX_DEFAULT_PORT}" networks: - app-network depends_on: config-generator: condition: service_completed_successfully tenants-app: image: ${DOCKER_REPO}/tenants-app:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] volumes: - config-volume:/config-inject:ro entrypoint: > sh -c "cp /config-inject/config.json /usr/share/nginx/html/config.json && nginx -g 'daemon off;'" ports: - "${FRONTEND_TENANTS_APP_INTERNAL_PORT}:${NGINX_DEFAULT_PORT}" networks: - app-network depends_on: config-generator: condition: service_completed_successfully suite-app: image: ${DOCKER_REPO}/suite-app:${IMAGEM_UNSTABLE_LATEST} profiles: ["app"] volumes: - config-volume:/config-inject:ro entrypoint: > sh -c "cp /config-inject/config.json /usr/share/nginx/html/config.json && nginx -g 'daemon off;'" ports: - "${FRONTEND_SUITE_APP_INTERNAL_PORT}:${NGINX_DEFAULT_PORT}" networks: - app-network depends_on: config-generator: condition: service_completed_successfully networks: app-network: name: attendancesystem-network volumes: mongodb_data: postgres_data: rabbitmq_data: config-volume: