name: humainflow-data-stack x-logging: &default-logging driver: json-file options: max-size: "10m" max-file: "3" services: postgres: image: ${POSTGRES_IMAGE:-postgres:17.11-alpine} environment: POSTGRES_DB: ${POSTGRES_DB:-humainflow} POSTGRES_USER: ${POSTGRES_USER:-humainflow} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env} POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256 POSTGRES_HOST_AUTH_METHOD: scram-sha-256 command: - postgres - -c - password_encryption=scram-sha-256 volumes: # A host directory when POSTGRES_DATA_PATH is set (see the README), the named volume when not. - ${POSTGRES_DATA_PATH:-postgres-data}:/var/lib/postgresql/data expose: - "5432" networks: - data-backend healthcheck: test: ["CMD-SHELL", "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""] interval: 10s timeout: 5s retries: 10 start_period: 10s shm_size: 256mb restart: unless-stopped stop_grace_period: 60s logging: *default-logging minio: # Pinned to the version minio.Dockerfile builds. Upstream publishes no image for this release, so # the image is built and pushed by publish-images.sh; the server only pulls it. image: ${MINIO_IMAGE:-luciolelii/minio:RELEASE.2025-10-15T17-29-55Z} environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:?set MINIO_ROOT_USER in .env} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD in .env} # Required for presigned URLs generated while MinIO is behind Caddy. MINIO_SERVER_URL: https://${DATA_DOMAIN:?set DATA_DOMAIN in .env} # The console has its own public port on the same name, and the redirect must carry it. MINIO_BROWSER_REDIRECT_URL: https://${DATA_DOMAIN}:${CONSOLE_PUBLIC_PORT:-9443} command: ["server", "/data", "--console-address", ":9001"] volumes: # A host directory when MINIO_DATA_PATH is set (see the README), the named volume when not. - ${MINIO_DATA_PATH:-minio-data}:/data expose: - "9000" - "9001" networks: - data-backend healthcheck: test: ["CMD", "wget", "--spider", "--quiet", "http://127.0.0.1:9000/minio/health/live"] interval: 10s timeout: 5s retries: 10 start_period: 15s restart: unless-stopped stop_grace_period: 60s logging: *default-logging pgadmin: image: dpage/pgadmin4:9.18 environment: PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:?set PGADMIN_DEFAULT_EMAIL in .env} PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:?set PGADMIN_DEFAULT_PASSWORD in .env} # Caddy terminates TLS. pgAdmin listens only on the private Docker network. PGADMIN_LISTEN_ADDRESS: 0.0.0.0 PGADMIN_LISTEN_PORT: 5050 PGADMIN_DISABLE_POSTFIX: "true" PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION: "True" PGADMIN_CONFIG_SESSION_COOKIE_SECURE: "True" PGADMIN_CONFIG_UPGRADE_CHECK_ENABLED: "False" volumes: - pgadmin-data:/var/lib/pgadmin expose: - "5050" networks: - data-backend depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1:5050/misc/ping"] interval: 15s timeout: 10s retries: 10 start_period: 30s cap_drop: - ALL security_opt: - no-new-privileges:true pids_limit: 256 mem_limit: 512m cpus: 1 restart: unless-stopped logging: *default-logging caddy: # Caddy with the caddy-l4 module, built from caddy.Dockerfile by publish-images.sh. The tag is the # Caddy version followed by the module's. image: ${CADDY_IMAGE:-luciolelii/caddy-l4:2.11.4-l4-v0.1.2} environment: TLS_CONTACT: ${TLS_CONTACT:?set TLS_CONTACT in .env} DATA_DOMAIN: ${DATA_DOMAIN:?set DATA_DOMAIN in .env} ports: # 80/443 are used for ACME challenges, HTTPS and redirects. - "${PUBLIC_BIND_ADDRESS:-0.0.0.0}:${HTTP_PUBLIC_PORT:-80}:80" - "${PUBLIC_BIND_ADDRESS:-0.0.0.0}:${HTTPS_PUBLIC_PORT:-443}:443" # PostgreSQL-over-TLS is terminated by Caddy's Layer 4 module. - "${PUBLIC_BIND_ADDRESS:-0.0.0.0}:${POSTGRES_PUBLIC_PORT:-5432}:5432" # The MinIO console and pgAdmin, on the same name as everything else but their own ports. - "${PUBLIC_BIND_ADDRESS:-0.0.0.0}:${CONSOLE_PUBLIC_PORT:-9443}:9443" - "${PUBLIC_BIND_ADDRESS:-0.0.0.0}:${PGADMIN_PUBLIC_PORT:-5443}:5443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro # Certificates, private keys and the ACME account must survive restarts. - caddy-data:/data - caddy-config:/config networks: - edge - data-backend depends_on: postgres: condition: service_healthy minio: condition: service_healthy pgadmin: condition: service_healthy cap_drop: - ALL cap_add: - NET_BIND_SERVICE security_opt: - no-new-privileges:true read_only: true pids_limit: 128 mem_limit: 256m cpus: 1 restart: unless-stopped logging: *default-logging networks: edge: data-backend: internal: true volumes: postgres-data: minio-data: pgadmin-data: caddy-data: caddy-config: