x-django-service: &django-service build: context: . dockerfile: Dockerfile restart: unless-stopped init: true networks: - coolify environment: &django-environment DJANGO_SETTINGS_MODULE: config.settings.prod DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:?Set DJANGO_SECRET_KEY in Coolify} DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:?Set DJANGO_ALLOWED_HOSTS in Coolify} CSRF_TRUSTED_ORIGINS: ${CSRF_TRUSTED_ORIGINS:?Set CSRF_TRUSTED_ORIGINS in Coolify} PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:?Set PUBLIC_BASE_URL in Coolify} WEBOTP_HOST: ${WEBOTP_HOST:-} TIME_ZONE: ${TIME_ZONE:-Asia/Tehran} DATABASE_URL: ${DATABASE_URL:-} POSTGRES_DB: ${POSTGRES_DB:-customerTicket} POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-} POSTGRES_HOST: ${POSTGRES_HOST:-} POSTGRES_PORT: ${POSTGRES_PORT:-5432} DB_CONN_MAX_AGE: ${DB_CONN_MAX_AGE:-60} DB_CONNECT_TIMEOUT: ${DB_CONNECT_TIMEOUT:-10} DB_SSLMODE: ${DB_SSLMODE:-prefer} DATABASE_WAIT_TIMEOUT: ${DATABASE_WAIT_TIMEOUT:-60} PRODUCTION_SEED_DIR: /app/production-seed REQUIRE_PRODUCTION_SEED: ${REQUIRE_PRODUCTION_SEED:-1} MEDIA_ROOT: /app/media MEDIA_SIGNING_SECRET: ${MEDIA_SIGNING_SECRET:?} USE_NGINX_MEDIA: "true" SMS_PROVIDER_CLASS: ${SMS_PROVIDER_CLASS:-apps.integrations.sms.sms0098.ZeroZeroNinetyEightSMSProvider} SMS0098_USERNAME: ${SMS0098_USERNAME:-} SMS0098_PASSWORD: ${SMS0098_PASSWORD:-} SMS0098_FROM: ${SMS0098_FROM:-} SMS0098_WSDL_URL: ${SMS0098_WSDL_URL:-https://webservice.0098sms.com/service.asmx?WSDL} BEHIN_SMS_USERNAME: ${BEHIN_SMS_USERNAME:-} BEHIN_SMS_PASSWORD: ${BEHIN_SMS_PASSWORD:-} BEHIN_SMS_SPECIAL_NUMBER: ${BEHIN_SMS_SPECIAL_NUMBER:-} BEHIN_SMS_WSDL_URL: ${BEHIN_SMS_WSDL_URL:-http://panel.behinsms.com/SMSWS/SOAP.asmx?wsdl} SMS_API_URL: ${SMS_API_URL:-} SMS_API_TOKEN: ${SMS_API_TOKEN:-} SMS_SENDER: ${SMS_SENDER:-} BALE_API_BASE: ${BALE_API_BASE:-https://tapi.bale.ai} BALE_BOT_TOKEN: ${BALE_BOT_TOKEN:-} INTEGRATION_HTTP_TIMEOUT_SECONDS: ${INTEGRATION_HTTP_TIMEOUT_SECONDS:-10} MAX_NOTIFICATION_ATTEMPTS: ${MAX_NOTIFICATION_ATTEMPTS:-5} SMS_MAX_RETRIES: ${SMS_MAX_RETRIES:-3} SMS_RETRY_DELAY_SECONDS: ${SMS_RETRY_DELAY_SECONDS:-180} SMS_DELIVERY_CHECK_DELAY_SECONDS: ${SMS_DELIVERY_CHECK_DELAY_SECONDS:-180} SMS_DELIVERY_MAX_CHECKS: ${SMS_DELIVERY_MAX_CHECKS:-15} SECURE_SSL_REDIRECT: ${SECURE_SSL_REDIRECT:-true} SECURE_HSTS_SECONDS: ${SECURE_HSTS_SECONDS:-31536000} SECURE_HSTS_INCLUDE_SUBDOMAINS: ${SECURE_HSTS_INCLUDE_SUBDOMAINS:-true} SECURE_HSTS_PRELOAD: ${SECURE_HSTS_PRELOAD:-false} services: web: <<: *django-service environment: <<: *django-environment RUN_STARTUP_TASKS: "1" expose: - "8000" volumes: - static_data:/app/staticfiles - media_data:/app/media - seed_data:/app/production-seed:ro healthcheck: test: ["CMD", "python", "-c", "import http.client,os; c=http.client.HTTPConnection('127.0.0.1',8000,timeout=5); c.request('GET','/healthz/',headers={'Host':os.getenv('HEALTHCHECK_HOST','localhost'),'X-Forwarded-Proto':'https'}); r=c.getresponse(); raise SystemExit(0 if r.status==200 else 1)"] interval: 15s timeout: 7s retries: 8 start_period: 45s stop_grace_period: 35s notification-worker: <<: *django-service command: ["python", "manage.py", "process_notifications"] depends_on: web: condition: service_healthy volumes: - media_data:/app/media stop_grace_period: 20s nginx: build: context: . dockerfile: Dockerfile.nginx args: NGINX_IMAGE: ${NGINX_IMAGE:-nginx:1.27-alpine} restart: unless-stopped networks: - coolify labels: # Coolify generates the Host/PathPrefix/TLS rules from the three nginx # Domains entries. Pin those generated routers to this container and give # them precedence over web's catch-all PathPrefix(`/`) router. - "traefik.enable=true" - "traefik.docker.network=${COOLIFY_RESOURCE_UUID:?}" - "traefik.http.services.customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}.loadbalancer.server.port=80" - "traefik.http.routers.http-0-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" - "traefik.http.routers.http-0-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" - "traefik.http.routers.http-1-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" - "traefik.http.routers.http-1-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" - "traefik.http.routers.http-2-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" - "traefik.http.routers.http-2-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" - "traefik.http.routers.https-0-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" - "traefik.http.routers.https-0-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" - "traefik.http.routers.https-1-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" - "traefik.http.routers.https-1-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" - "traefik.http.routers.https-2-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" - "traefik.http.routers.https-2-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" expose: - "80" depends_on: web: condition: service_healthy volumes: - static_data:/app/staticfiles:ro - media_data:/app/media:ro environment: MEDIA_SIGNING_SECRET: ${MEDIA_SIGNING_SECRET:?} healthcheck: test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1/healthz/ || exit 1"] interval: 15s timeout: 7s retries: 5 start_period: 10s volumes: static_data: external: true name: ${STATIC_VOLUME_NAME:-customer_ticket_static} media_data: external: true name: ${MEDIA_VOLUME_NAME:-customer_ticket_media} seed_data: external: true name: ${SEED_VOLUME_NAME:-customer_ticket_seed} networks: coolify: external: true