# 部署拓扑:PostgreSQL 与 Web 应用都在 Docker 内。 # - db:PostgreSQL 16 (alpine,镜像小),数据持久化在 pgdata 卷 # - app:Gunicorn 2 worker × 2 线程(对应 1 物理核心 / 2 逻辑核心),限制 2G 内存 services: db: image: postgres:16-alpine container_name: cal-display-db restart: unless-stopped environment: - POSTGRES_USER=iot - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-iot} - POSTGRES_DB=iot_dboard - TZ=UTC volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U iot -d iot_dboard"] interval: 5s timeout: 3s retries: 12 deploy: resources: limits: cpus: "0.5" memory: 512M app: build: . container_name: cal-display restart: unless-stopped ports: - "5000:5000" volumes: # 挂载目录:可放置待导入的旧 SQLite db 文件(也支持 /control 设置页直接上传导入) - ./data:/app/data # 持久化项目代码(首次自动初始化为镜像内代码,之后 git pull 生效) - app_code:/app environment: - DATABASE_URL=postgresql://iot:${POSTGRES_PASSWORD:-iot}@db:5432/iot_dboard - FLASK_SECRET_KEY=${FLASK_SECRET_KEY:-} - FLASK_HTTPS=${FLASK_HTTPS:-} - GUNICORN_WORKERS=${GUNICORN_WORKERS:-2} - GUNICORN_THREADS=${GUNICORN_THREADS:-8} depends_on: db: condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:5000/api/auth/status', timeout=3)"] interval: 30s timeout: 5s retries: 3 start_period: 20s deploy: resources: limits: # 1 物理核心 = 2 逻辑核心 + 2G 内存 cpus: "2" memory: 2G volumes: pgdata: app_code: