services: # =========================================== # Infrastructure # =========================================== postgres: image: postgres:16-alpine environment: POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 restart: unless-stopped rabbitmq: image: rabbitmq:3-management-alpine environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-guest} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-guest} volumes: - rabbitmq_data:/var/lib/rabbitmq healthcheck: test: ["CMD", "rabbitmq-diagnostics", "check_running"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # =========================================== # Backend Services # =========================================== novel-service: build: context: . dockerfile: FictionArchive.Service.NovelService/Dockerfile environment: ConnectionStrings__DefaultConnection: Host=postgres;Database=FictionArchive_NovelService;Username=${POSTGRES_USER:-postgres};Password=${POSTGRES_PASSWORD:-postgres} ConnectionStrings__RabbitMQ: amqp://${RABBITMQ_USER:-guest}:${RABBITMQ_PASSWORD:-guest}@rabbitmq Novelpia__Username: ${NOVELPIA_USERNAME} Novelpia__Password: ${NOVELPIA_PASSWORD} NovelUpdateService__PendingImageUrl: https://files.fictionarchive.orfl.xyz/api/pendingupload.png depends_on: postgres: condition: service_healthy rabbitmq: condition: service_healthy restart: unless-stopped translation-service: build: context: . dockerfile: FictionArchive.Service.TranslationService/Dockerfile environment: ConnectionStrings__DefaultConnection: Host=postgres;Database=FictionArchive_TranslationService;Username=${POSTGRES_USER:-postgres};Password=${POSTGRES_PASSWORD:-postgres} ConnectionStrings__RabbitMQ: amqp://${RABBITMQ_USER:-guest}:${RABBITMQ_PASSWORD:-guest}@rabbitmq DeepL__ApiKey: ${DEEPL_API_KEY} depends_on: postgres: condition: service_healthy rabbitmq: condition: service_healthy restart: unless-stopped scheduler-service: build: context: . dockerfile: FictionArchive.Service.SchedulerService/Dockerfile environment: ConnectionStrings__DefaultConnection: Host=postgres;Database=FictionArchive_SchedulerService;Username=${POSTGRES_USER:-postgres};Password=${POSTGRES_PASSWORD:-postgres} ConnectionStrings__RabbitMQ: amqp://${RABBITMQ_USER:-guest}:${RABBITMQ_PASSWORD:-guest}@rabbitmq depends_on: postgres: condition: service_healthy rabbitmq: condition: service_healthy restart: unless-stopped user-service: build: context: . dockerfile: FictionArchive.Service.UserService/Dockerfile environment: ConnectionStrings__DefaultConnection: Host=postgres;Database=FictionArchive_UserService;Username=${POSTGRES_USER:-postgres};Password=${POSTGRES_PASSWORD:-postgres} ConnectionStrings__RabbitMQ: amqp://${RABBITMQ_USER:-guest}:${RABBITMQ_PASSWORD:-guest}@rabbitmq depends_on: postgres: condition: service_healthy rabbitmq: condition: service_healthy restart: unless-stopped authentication-service: build: context: . dockerfile: FictionArchive.Service.AuthenticationService/Dockerfile environment: ConnectionStrings__RabbitMQ: amqp://${RABBITMQ_USER:-guest}:${RABBITMQ_PASSWORD:-guest}@rabbitmq depends_on: rabbitmq: condition: service_healthy restart: unless-stopped file-service: build: context: . dockerfile: FictionArchive.Service.FileService/Dockerfile environment: ConnectionStrings__RabbitMQ: amqp://${RABBITMQ_USER:-guest}:${RABBITMQ_PASSWORD:-guest}@rabbitmq S3__Endpoint: ${S3_ENDPOINT:-https://s3.orfl.xyz} S3__Bucket: ${S3_BUCKET:-fictionarchive} S3__AccessKey: ${S3_ACCESS_KEY} S3__SecretKey: ${S3_SECRET_KEY} Proxy__BaseUrl: https://files.orfl.xyz/api labels: - "traefik.enable=true" - "traefik.http.routers.file-service.rule=Host(`files.orfl.xyz`)" - "traefik.http.routers.file-service.entrypoints=websecure" - "traefik.http.routers.file-service.tls.certresolver=letsencrypt" - "traefik.http.services.file-service.loadbalancer.server.port=8080" depends_on: rabbitmq: condition: service_healthy restart: unless-stopped # =========================================== # API Gateway # =========================================== api-gateway: build: context: . dockerfile: FictionArchive.API/Dockerfile environment: ConnectionStrings__RabbitMQ: amqp://${RABBITMQ_USER:-guest}:${RABBITMQ_PASSWORD:-guest}@rabbitmq labels: - "traefik.enable=true" - "traefik.http.routers.api-gateway.rule=Host(`api.fictionarchive.orfl.xyz`)" - "traefik.http.routers.api-gateway.entrypoints=websecure" - "traefik.http.routers.api-gateway.tls.certresolver=letsencrypt" - "traefik.http.services.api-gateway.loadbalancer.server.port=8080" depends_on: - novel-service - translation-service - scheduler-service - user-service - authentication-service - file-service restart: unless-stopped # =========================================== # Frontend # =========================================== frontend: build: context: ./fictionarchive-web dockerfile: Dockerfile args: VITE_GRAPHQL_URI: https://api.fictionarchive.orfl.xyz/graphql/ VITE_OIDC_AUTHORITY: ${OIDC_AUTHORITY:-https://auth.orfl.xyz/application/o/fiction-archive/} VITE_OIDC_CLIENT_ID: ${OIDC_CLIENT_ID} VITE_OIDC_REDIRECT_URI: https://fictionarchive.orfl.xyz/ VITE_OIDC_POST_LOGOUT_REDIRECT_URI: https://fictionarchive.orfl.xyz/ labels: - "traefik.enable=true" - "traefik.http.routers.frontend.rule=Host(`fictionarchive.orfl.xyz`)" - "traefik.http.routers.frontend.entrypoints=websecure" - "traefik.http.routers.frontend.tls.certresolver=letsencrypt" - "traefik.http.services.frontend.loadbalancer.server.port=80" restart: unless-stopped volumes: postgres_data: rabbitmq_data: letsencrypt: