x-logging: &default-logging driver: "json-file" options: max-size: "150m" max-file: "2" services: nginx: image: nginx:1.30.1 logging: *default-logging restart: unless-stopped ports: - "${PORT:-80}:80" - "${PORT:-443:443}" depends_on: web: condition: service_healthy anubis: condition: service_healthy networks: - main environment: - DOMAIN=${DOMAIN} - MAX_UPLOAD_MiB=${DATA_UPLOAD_MAX_MEMORY_MiB:-100} volumes: - ./nginx/${NGINX_SETUP:-https}.conf:/etc/nginx/templates/default.conf.template - ./nginx/server_config:/etc/nginx/templates/server_config.template - ./nginx/server_name:/etc/nginx/templates/server_name.template - ./nginx/locations:/etc/nginx/conf.d/locations - ./nginx/99-autoreload.sh:/docker-entrypoint.d/99-autoreload.sh - ./certbot/conf:/etc/nginx/ssl - ./certbot/data:/var/www/certbot - static_volume:/app/static - media_volume:/app/images anubis: image: ghcr.io/techarohq/anubis:v1.28.2 restart: unless-stopped environment: BIND: ":8000" DIFFICULTY: "4" METRICS_BIND: ":9090" SERVE_ROBOTS_TXT: "true" TARGET: "http://web:8000" POLICY_FNAME: "/data/cfg/botPolicy.yaml" OG_PASSTHROUGH: "true" OG_EXPIRY_TIME: "24h" healthcheck: test: ["CMD", "anubis", "--healthcheck"] interval: 5s timeout: 30s retries: 5 start_period: 500ms depends_on: web: condition: service_healthy networks: - main volumes: - "./anubis/botPolicy.yaml:/data/cfg/botPolicy.yaml:ro" certbot: image: certbot/certbot:latest restart: unless-stopped entrypoint: /bin/sh -c "trap exit TERM; while [ "${NGINX_SETUP:-https}" = "https" ];do certbot renew --webroot --webroot-path=/var/www/certbot; sleep 1d & wait $${!}; done; while [ "${NGINX_SETUP:-https}" != "https" ];do sleep infinity & wait $${!}; done;" depends_on: - nginx volumes: - ./certbot/conf:/etc/letsencrypt - ./certbot/logs:/var/log/letsencrypt - ./certbot/data:/var/www/certbot db-backup-job: build: postgres-docker environment: - DEBUG=${DEBUG} - PGPASSWORD=${POSTGRES_PASSWORD} - PGHOST=${POSTGRES_HOST} - PGUSER=${POSTGRES_USER} - PGDATABASE=${POSTGRES_DB} depends_on: db: condition: service_started volumes: - backups:/backups networks: - main db: image: postgres:17 restart: unless-stopped shm_size: ${POSTGRES_SHM_SIZE:-128mb} env_file: .env healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s retries: 5 start_period: 5s timeout: 10s volumes: - pgdata:/var/lib/postgresql/data networks: - main web: build: . restart: unless-stopped env_file: .env command: gunicorn bookwyrm.wsgi:application volumes: - static_volume:/app/static - media_volume:/app/images - exports_volume:/app/exports healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8000"] interval: 3s timeout: 1s start_period: 3s retries: 25 depends_on: db: condition: service_healthy redis_activity: condition: service_started networks: - main redis_activity: image: redis:7.2.1 command: redis-server --requirepass ${REDIS_ACTIVITY_PASSWORD} --appendonly yes --port ${REDIS_ACTIVITY_PORT} logging: *default-logging volumes: - ./redis.conf:/etc/redis/redis.conf - redis_activity_data:/data env_file: .env networks: - main restart: unless-stopped redis_broker: image: redis:7.2.1 command: redis-server --requirepass ${REDIS_BROKER_PASSWORD} --appendonly yes --port ${REDIS_BROKER_PORT} logging: *default-logging volumes: - ./redis.conf:/etc/redis/redis.conf - redis_broker_data:/data env_file: .env networks: - main restart: unless-stopped celery_worker: env_file: .env build: . networks: - main command: celery -A celerywyrm worker --pool=threads --concurrency=20 -l info -Q high_priority,medium_priority,low_priority,streams,images,suggested_users,email,connectors,lists,inbox,imports,import_triggered,broadcast,dedupe,misc healthcheck: test: celery -A celerywyrm status interval: 10s timeout: 10s start_period: 2s retries: 6 volumes: - static_volume:/app/static - media_volume:/app/images - exports_volume:/app/exports depends_on: web: condition: service_healthy db: condition: service_healthy redis_broker: condition: service_started restart: unless-stopped celery_beat: env_file: .env build: . networks: - main command: celery -A celerywyrm beat -l INFO --scheduler django_celery_beat.schedulers:DatabaseScheduler healthcheck: test: celery -A celerywyrm status interval: 10s timeout: 10s retries: 6 start_period: 2s volumes: - static_volume:/app/static - media_volume:/app/images - exports_volume:/app/exports depends_on: celery_worker: condition: service_healthy restart: unless-stopped flower: build: . command: celery -A celerywyrm flower --basic_auth=${FLOWER_USER}:${FLOWER_PASSWORD} --url_prefix=flower healthcheck: test: celery -A celerywyrm status interval: 10s timeout: 10s retries: 6 start_period: 2s env_file: .env volumes: - static_volume:/app/static networks: - main depends_on: db: condition: service_healthy redis_broker: condition: service_started web: condition: service_healthy restart: unless-stopped volumes: pgdata: backups: static_volume: media_volume: exports_volume: redis_broker_data: redis_activity_data: networks: main: enable_ipv6: true