version: "3.8" services: postgres: image: postgres:16-alpine container_name: postgres environment: POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} POSTGRES_DB: ${POSTGRES_DB:-flower} ports: - "5432:5432" volumes: - db_data:/var/lib/postgresql/data dns: - 8.8.8.8 - 8.8.4.4 healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"] interval: 5s timeout: 3s retries: 10 start_period: 10s restart: unless-stopped pgbouncer: image: pgbouncer/pgbouncer:latest container_name: pgbouncer # 使用环境变量配置,让镜像自动生成配置文件 environment: # 数据库连接配置(格式:数据库名=host=主机 port=端口 dbname=数据库名 user=用户 password=密码) DATABASES: flower=host=postgres port=${POSTGRES_PORT:-5432} dbname=${POSTGRES_DB:-flower} user=${POSTGRES_USER:-postgres} password=${POSTGRES_PASSWORD:-postgres} # PgBouncer 基本配置 PGBOUNCER_LISTEN_ADDR: 0.0.0.0 PGBOUNCER_LISTEN_PORT: 6432 PGBOUNCER_AUTH_TYPE: trust # 连接池配置 PGBOUNCER_POOL_MODE: transaction PGBOUNCER_MAX_CLIENT_CONN: "100" PGBOUNCER_DEFAULT_POOL_SIZE: "25" PGBOUNCER_MIN_POOL_SIZE: "5" PGBOUNCER_RESERVE_POOL_SIZE: "5" PGBOUNCER_RESERVE_POOL_TIMEOUT: "3" # 连接超时设置 PGBOUNCER_SERVER_CONNECT_TIMEOUT: "15" PGBOUNCER_SERVER_IDLE_TIMEOUT: "600" PGBOUNCER_QUERY_TIMEOUT: "0" PGBOUNCER_QUERY_WAIT_TIMEOUT: "120" # 日志配置 PGBOUNCER_LOG_CONNECTIONS: "1" PGBOUNCER_LOG_DISCONNECTIONS: "1" PGBOUNCER_LOG_POOLER_ERRORS: "1" # 其他设置 PGBOUNCER_IGNORE_STARTUP_PARAMETERS: extra_float_digits PGBOUNCER_APPLICATION_NAME_ADD_HOST: "1" ports: - "${PGBOUNCER_PORT:-6432}:6432" # 确保 postgres 完全启动后再启动 pgbouncer depends_on: postgres: condition: service_healthy # DNS 配置:使用 Docker 内置 DNS,并添加 DNS 搜索域 dns: - 8.8.8.8 - 8.8.4.4 restart: unless-stopped redis: image: redis:7-alpine container_name: redis volumes: - redis_data:/data restart: unless-stopped rabbitmq: image: rabbitmq:3-management-alpine container_name: rabbitmq environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-guest} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:-guest} volumes: - rabbitmq_data:/var/lib/rabbitmq restart: unless-stopped web: image: ${FLOWER_IMAGE:-flower-app:latest} container_name: flower_web command: - uvicorn - flower.asgi:application - --host - 0.0.0.0 - --port - "8000" - --workers - "${UVICORN_WORKERS:-1}" ports: - "${WEB_PORT:-8000}:8000" environment: DJANGO_SETTINGS_MODULE: flower.settings PYTHONPATH: /app DEBUG: "${DEBUG:-0}" ALLOWED_HOSTS: "${ALLOWED_HOSTS:-yuwenerp.yuwen.cloud}" DB_HOST: ${DB_HOST:-pgbouncer} DB_PORT: "${DB_PORT:-6432}" DB_NAME: "${DB_NAME:-flower}" DB_USER: "${DB_USER:-postgres}" DB_PASSWORD: "${DB_PASSWORD:-postgres}" CELERY_BROKER_URL: "${CELERY_BROKER_URL:-amqp://guest:guest@rabbitmq:5672//}" CELERY_RESULT_BACKEND: "${CELERY_RESULT_BACKEND:-redis://redis:6379/0}" depends_on: - pgbouncer - postgres - redis - rabbitmq restart: unless-stopped celery_worker: image: ${FLOWER_IMAGE:-flower-app:latest} container_name: celery_worker command: - celery - -A - flower - worker - -l - info - --concurrency=${CELERY_CONCURRENCY:-2} - --pool=solo environment: PYTHONPATH: /app DB_HOST: ${DB_HOST:-pgbouncer} DB_PORT: "${DB_PORT:-6432}" DB_NAME: "${DB_NAME:-flower}" DB_USER: "${DB_USER:-postgres}" DB_PASSWORD: "${DB_PASSWORD:-postgres}" CELERY_BROKER_URL: "${CELERY_BROKER_URL:-amqp://guest:guest@rabbitmq:5672//}" CELERY_RESULT_BACKEND: "${CELERY_RESULT_BACKEND:-redis://redis:6379/0}" # 数据库备份输出目录(api_v1.tasks.backup_database 默认输出到 BASE_DIR/data-bak) volumes: # 默认落在 compose 同级目录的 ./data-bak,方便宿主机直接查看/拷贝 # 也可通过 BACKUP_DIR 指定绝对路径,如 /srv/flower/data-bak - ${BACKUP_DIR:-./data-bak}:/app/data-bak depends_on: - pgbouncer - postgres - redis - rabbitmq restart: unless-stopped celery_beat: image: ${FLOWER_IMAGE:-flower-app:latest} container_name: celery_beat command: - celery - -A - flower - beat - -l - info - --schedule - /var/lib/celery/celerybeat-schedule environment: DJANGO_SETTINGS_MODULE: flower.settings PYTHONPATH: /app DB_HOST: ${DB_HOST:-pgbouncer} DB_PORT: "${DB_PORT:-6432}" DB_NAME: "${DB_NAME:-flower}" DB_USER: "${DB_USER:-postgres}" DB_PASSWORD: "${DB_PASSWORD:-postgres}" CELERY_BROKER_URL: "${CELERY_BROKER_URL:-amqp://guest:guest@rabbitmq:5672//}" CELERY_RESULT_BACKEND: "${CELERY_RESULT_BACKEND:-redis://redis:6379/0}" # Celery Beat 的持久化调度文件,避免重启后重复/错过调度 volumes: - celery_beat_data:/var/lib/celery depends_on: - pgbouncer - postgres - redis - rabbitmq restart: unless-stopped volumes: db_data: redis_data: rabbitmq_data: celery_beat_data: