services: postgres: image: postgres:15-alpine container_name: rfiles-db restart: unless-stopped volumes: - rfiles_postgres_data:/var/lib/postgresql/data environment: - POSTGRES_DB=rfiles - POSTGRES_USER=rfiles - POSTGRES_PASSWORD=${DB_PASSWORD} healthcheck: test: ["CMD-SHELL", "pg_isready -U rfiles -d rfiles"] interval: 10s timeout: 5s retries: 5 cap_drop: - ALL cap_add: - DAC_OVERRIDE - FOWNER - SETGID - SETUID security_opt: - no-new-privileges:true networks: - rfiles-internal redis: image: redis:7-alpine container_name: rfiles-redis restart: unless-stopped command: redis-server --requirepass ${REDIS_PASSWORD} volumes: - rfiles_redis_data:/data healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 5 cap_drop: - ALL cap_add: - SETGID - SETUID security_opt: - no-new-privileges:true networks: - rfiles-internal backend: build: context: . dockerfile: Dockerfile container_name: rfiles-api restart: unless-stopped volumes: - rfiles_media:/app/media - rfiles_static:/app/staticfiles environment: - DATABASE_URL=postgresql://rfiles:${DB_PASSWORD}@postgres:5432/rfiles - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD}@redis:6379/0 - DJANGO_SETTINGS_MODULE=config.settings - DEBUG=False - ALLOWED_HOSTS=rfiles.online,www.rfiles.online,.rfiles.online,direct.rfiles.online,localhost - SHARE_BASE_URL=https://rfiles.online - SECRET_KEY=${SECRET_KEY} depends_on: postgres: condition: service_healthy redis: condition: service_healthy labels: - "traefik.enable=true" # Main router (via Cloudflare tunnel → port 80) - "traefik.http.routers.rfiles.rule=Host(`rfiles.online`) || Host(`www.rfiles.online`) || HostRegexp(`{subdomain:[a-z0-9-]+}.rfiles.online`)" - "traefik.http.routers.rfiles.entrypoints=web" # Direct upload router (bypasses Cloudflare, TLS via Let's Encrypt) - "traefik.http.routers.rfiles-direct.rule=Host(`direct.rfiles.online`)" - "traefik.http.routers.rfiles-direct.entrypoints=websecure" - "traefik.http.routers.rfiles-direct.tls=true" - "traefik.http.routers.rfiles-direct.tls.certresolver=letsencrypt" - "traefik.http.services.rfiles.loadbalancer.server.port=8000" - "traefik.docker.network=traefik-public" cap_drop: - ALL cap_add: - CHOWN - SETGID - SETUID security_opt: - no-new-privileges:true read_only: true tmpfs: - /tmp networks: - rfiles-internal - traefik-public command: > sh -c "python manage.py migrate --noinput && python manage.py collectstatic --noinput && gunicorn config.wsgi:application --bind 0.0.0.0:8000 --workers 4 --threads 2" celery-worker: build: context: . dockerfile: Dockerfile container_name: rfiles-celery-worker restart: unless-stopped volumes: - rfiles_media:/app/media environment: - DATABASE_URL=postgresql://rfiles:${DB_PASSWORD}@postgres:5432/rfiles - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD}@redis:6379/0 - DJANGO_SETTINGS_MODULE=config.settings - SECRET_KEY=${SECRET_KEY} depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD-SHELL", "celery -A config inspect ping --timeout 10 | grep -q 'pong'"] interval: 30s timeout: 15s start_period: 40s retries: 3 cap_drop: - ALL security_opt: - no-new-privileges:true read_only: true tmpfs: - /tmp networks: - rfiles-internal command: celery -A config worker --loglevel=info --concurrency=2 celery-beat: build: context: . dockerfile: Dockerfile container_name: rfiles-celery-beat restart: unless-stopped environment: - DATABASE_URL=postgresql://rfiles:${DB_PASSWORD}@postgres:5432/rfiles - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD}@redis:6379/0 - DJANGO_SETTINGS_MODULE=config.settings - SECRET_KEY=${SECRET_KEY} depends_on: - celery-worker healthcheck: test: ["CMD-SHELL", "test -f /tmp/celerybeat-schedule"] interval: 30s timeout: 5s start_period: 40s retries: 3 cap_drop: - ALL security_opt: - no-new-privileges:true read_only: true tmpfs: - /tmp networks: - rfiles-internal command: celery -A config beat --loglevel=info --schedule=/tmp/celerybeat-schedule volumes: rfiles_postgres_data: rfiles_redis_data: rfiles_media: rfiles_static: networks: rfiles-internal: driver: bridge traefik-public: external: true