name: gochat-production x-gochat-image: &gochat-image ${GOCHAT_IMAGE_REF:?set GOCHAT_IMAGE_REF to an immutable image digest} x-postgres-tls-ca: &postgres-tls-ca type: bind source: ${GOCHAT_DATABASE_TLS_CA_FILE:-/dev/null} target: /run/secrets/external-db-ca.crt read_only: true bind: create_host_path: false x-postgres-tls-client-cert: &postgres-tls-client-cert type: bind source: ${GOCHAT_DATABASE_TLS_CLIENT_CERT_FILE:-/dev/null} target: /run/secrets/external-db-client.crt read_only: true bind: create_host_path: false x-postgres-tls-client-key: &postgres-tls-client-key type: bind source: ${GOCHAT_DATABASE_TLS_CLIENT_KEY_FILE:-/dev/null} target: /run/secrets/external-db-client.key read_only: true bind: create_host_path: false x-database-client-entrypoint: &database-client-entrypoint type: bind source: ./database_client_entrypoint.sh target: /usr/local/bin/database-client-entrypoint read_only: true bind: create_host_path: false x-gochat-logging: &gochat-logging driver: fluentd options: fluentd-address: 127.0.0.1:24224 fluentd-async: "true" fluentd-buffer-limit: "65536" tag: gochat.{{.Name}} x-gochat-environment: &gochat-environment GOCHAT_ENV: production GOCHAT_SERVER_HOST: 0.0.0.0 GOCHAT_SERVER_PORT: 3000 GOCHAT_SERVER_MODE: release GOCHAT_DATABASE_DSN: &gochat-database-dsn ${GOCHAT_DATABASE_DSN:?set an external PostgreSQL DSN with an explicit sslmode} GOCHAT_DATABASE_RUN_MIGRATIONS: "false" GOCHAT_DATABASE_MIGRATIONS_PATH: /app/migrations GOCHAT_REDIS_DSN: ${GOCHAT_REDIS_DSN:?set an external Redis DSN} GOCHAT_SEARCH_ENGINE: meilisearch GOCHAT_SEARCH_HOST: http://meilisearch:7700 GOCHAT_SEARCH_API_KEY: ${MEILI_MASTER_KEY:?set MEILI_MASTER_KEY} GOCHAT_JWT_SECRET: ${GOCHAT_JWT_SECRET:?set GOCHAT_JWT_SECRET} GOCHAT_JWT_PREVIOUS_SECRETS: ${GOCHAT_JWT_PREVIOUS_SECRETS:-} GOCHAT_ENCRYPTION_ENABLED: "true" GOCHAT_ENCRYPTION_CURRENT_KEY_VERSION: ${GOCHAT_ENCRYPTION_CURRENT_KEY_VERSION:-1} GOCHAT_ENCRYPTION_AES_KEY: ${GOCHAT_ENCRYPTION_AES_KEY:?set a base64-encoded 32-byte encryption key} GOCHAT_LOG_LEVEL: info GOCHAT_LOG_FORMAT: json GOCHAT_STORAGE_PROVIDER: local GOCHAT_STORAGE_LOCAL_PATH: /app/storage/uploads services: meilisearch: image: ${MEILI_IMAGE_REF:-getmeili/meilisearch:v1.13@sha256:bed3fb650e62da53145777204891159242f6ea4ce69e215b36223af4aa64a0ae} restart: always environment: MEILI_ENV: production MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:?set MEILI_MASTER_KEY} MEILI_NO_ANALYTICS: "true" volumes: - ./data/meilisearch:/meili_data healthcheck: test: ["CMD", "wget", "--no-verbose", "--spider", "http://127.0.0.1:7700/health"] interval: 5s timeout: 5s retries: 20 logging: *gochat-logging gochat: image: *gochat-image entrypoint: ["/usr/local/bin/database-client-entrypoint", "/app/gochat"] command: ["serve"] group_add: ["${GOCHAT_DATABASE_TLS_GID:-65534}"] restart: always stop_grace_period: ${GOCHAT_STOP_GRACE_PERIOD:-35s} depends_on: meilisearch: condition: service_healthy environment: *gochat-environment ports: - "127.0.0.1:${GOCHAT_PORT:-3000}:3000" volumes: - ./data/storage:/app/storage - *database-client-entrypoint - *postgres-tls-ca - *postgres-tls-client-cert - *postgres-tls-client-key healthcheck: test: ["CMD", "wget", "-q", "-T", "3", "-O", "/dev/null", "http://127.0.0.1:3000/ready"] interval: 10s timeout: 5s start_period: 15s retries: 30 deploy: resources: limits: memory: 512M cpus: "1.0" reservations: memory: 256M cpus: "0.5" logging: *gochat-logging worker: image: *gochat-image entrypoint: ["/usr/local/bin/database-client-entrypoint", "/app/gochat"] group_add: ["${GOCHAT_DATABASE_TLS_GID:-65534}"] restart: always stop_grace_period: ${GOCHAT_STOP_GRACE_PERIOD:-35s} depends_on: gochat: condition: service_healthy meilisearch: condition: service_healthy command: ["worker"] healthcheck: disable: true environment: <<: *gochat-environment GOCHAT_DATABASE_RUN_MIGRATIONS: "false" volumes: - ./data/storage:/app/storage - *database-client-entrypoint - *postgres-tls-ca - *postgres-tls-client-cert - *postgres-tls-client-key deploy: resources: limits: memory: 512M cpus: "1.0" logging: *gochat-logging migrate: image: *gochat-image profiles: ["ops"] entrypoint: ["/usr/local/bin/database-client-entrypoint", "/app/migrate"] group_add: ["${GOCHAT_DATABASE_TLS_GID:-65534}"] command: ["up"] restart: "no" environment: <<: *gochat-environment GOCHAT_DATABASE_RUN_MIGRATIONS: "false" PGOPTIONS: -c lock_timeout=5000 -c statement_timeout=900000 volumes: - *database-client-entrypoint - *postgres-tls-ca - *postgres-tls-client-cert - *postgres-tls-client-key logging: *gochat-logging backup: image: *gochat-image user: "0:0" profiles: ["ops"] entrypoint: ["/usr/local/bin/database-client-entrypoint", "/app/scripts/db_backup.sh"] group_add: ["${GOCHAT_DATABASE_TLS_GID:-65534}"] restart: "no" environment: GOCHAT_DATABASE_DSN: *gochat-database-dsn GOCHAT_STORAGE_PATH: /source/storage/uploads GOCHAT_CONNECTOR_BACKUP_FILE: /source/connector/${GOCHAT_CONNECTOR_BACKUP_NAME:-latest.db} GOCHAT_BACKUP_DIR: /backup/local GOCHAT_BACKUP_OFFSITE_DIR: /backup/offsite GOCHAT_BACKUP_PASSPHRASE_FILE: /run/secrets/backup-passphrase GOCHAT_BACKUP_RETENTION_DAYS: ${GOCHAT_BACKUP_RETENTION_DAYS:-30} GOCHAT_BACKUP_METRICS_FILE: /metrics/gochat_backup.prom GOCHAT_VERSION: ${GOCHAT_IMAGE_REF} volumes: - ./data/storage:/source/storage:ro - ./data/connector-backups:/source/connector:ro - ${GOCHAT_BACKUP_DIR:-./data/backups/local}:/backup/local - type: bind source: ${GOCHAT_BACKUP_OFFSITE_DIR:?set an existing external off-site mount point} target: /backup/offsite bind: create_host_path: false - ${GOCHAT_BACKUP_PASSPHRASE_FILE:-./.secrets/backup-passphrase}:/run/secrets/backup-passphrase:ro - ./data/backup-metrics:/metrics - *database-client-entrypoint - *postgres-tls-ca - *postgres-tls-client-cert - *postgres-tls-client-key logging: *gochat-logging restore: image: *gochat-image user: "0:0" profiles: ["ops"] entrypoint: ["/usr/local/bin/database-client-entrypoint", "/app/scripts/db_restore.sh"] group_add: ["${GOCHAT_DATABASE_TLS_GID:-65534}"] command: ["/backup/offsite/${GOCHAT_RESTORE_BUNDLE:-missing.tar.enc}"] restart: "no" environment: GOCHAT_DATABASE_DSN: *gochat-database-dsn GOCHAT_STORAGE_PATH: /restore/storage/uploads GOCHAT_CONNECTOR_DB_PATH: /restore/connector/connector.db GOCHAT_BACKUP_PASSPHRASE_FILE: /run/secrets/backup-passphrase volumes: - ./data/storage:/restore/storage - ./data/connector:/restore/connector - type: bind source: ${GOCHAT_BACKUP_OFFSITE_DIR:?set an existing external off-site mount point} target: /backup/offsite read_only: true bind: create_host_path: false - ${GOCHAT_BACKUP_PASSPHRASE_FILE:-./.secrets/backup-passphrase}:/run/secrets/backup-passphrase:ro - *database-client-entrypoint - *postgres-tls-ca - *postgres-tls-client-cert - *postgres-tls-client-key logging: *gochat-logging shangwutong: image: ${SHANGWUTONG_IMAGE_REF:?set SHANGWUTONG_IMAGE_REF to an immutable image digest} restart: always stop_grace_period: ${SWT_SHUTDOWN_TIMEOUT:-30s} environment: SWT_CONNECTOR_LISTEN: :9100 SWT_CONNECTOR_DB_PATH: /data/connector.db GOCHAT_BASE_URL: http://gochat:3000 GOCHAT_CONNECTOR_SERVICE_TOKEN: ${GOCHAT_CONNECTOR_SERVICE_TOKEN:-} SWT_MAX_INFLIGHT_HEARTBEATS: ${SWT_MAX_INFLIGHT_HEARTBEATS:-64} SWT_INBOUND_WORKERS: ${SWT_INBOUND_WORKERS:-8} SWT_OUTBOUND_WORKERS: ${SWT_OUTBOUND_WORKERS:-8} SWT_SHUTDOWN_TIMEOUT: ${SWT_SHUTDOWN_TIMEOUT:-30s} volumes: - ./data/connector:/data - ./data/connector-backups:/backup healthcheck: test: ["CMD", "wget", "-q", "-T", "3", "-O", "/dev/null", "http://127.0.0.1:9100/readyz"] interval: 30s timeout: 5s start_period: 15s retries: 3 deploy: resources: limits: memory: 512M cpus: "1.0" reservations: memory: 128M cpus: "0.25" logging: *gochat-logging fluentd: image: fluent/fluentd:v1.18-debian-1@sha256:f8d26db76ba06ce96e8d402119675071624dab724af49be40fd34641c347c440 restart: always ports: - "127.0.0.1:24224:24224" volumes: - ../fluentd/fluent.conf:/fluentd/etc/fluent.conf:ro - ./data/fluentd/log:/fluentd/log - ./data/fluentd/buffer:/fluentd/buffer postgres-exporter: image: quay.io/prometheuscommunity/postgres-exporter:v0.17.1@sha256:38606faa38c54787525fb0ff2fd6b41b4cfb75d455c1df294927c5f611699b17 restart: always entrypoint: ["/usr/local/bin/database-client-entrypoint", "/bin/postgres_exporter"] group_add: ["${GOCHAT_DATABASE_TLS_GID:-65534}"] command: ["--config.file=/dev/null", "--extend.query-path=/etc/postgres-exporter/queries.yml"] environment: DATA_SOURCE_NAME: *gochat-database-dsn volumes: - ../prometheus/postgres_queries.yml:/etc/postgres-exporter/queries.yml:ro - *database-client-entrypoint - *postgres-tls-ca - *postgres-tls-client-cert - *postgres-tls-client-key logging: *gochat-logging redis-exporter: image: oliver006/redis_exporter:v1.72.1@sha256:f90cae1e7ecc6ac223d04bdb0c95e084918baced9f81f08c3d01c2f11bff72bf restart: always environment: REDIS_ADDR: ${GOCHAT_REDIS_DSN:?set an external Redis DSN} logging: *gochat-logging blackbox-exporter: image: prom/blackbox-exporter:v0.27.0@sha256:a50c4c0eda297baa1678cd4dc4712a67fdea713b832d43ce7fcc5f9bea05094d restart: always command: ["--config.file=/etc/blackbox_exporter/config.yml"] volumes: - ../prometheus/blackbox.yml:/etc/blackbox_exporter/config.yml:ro logging: *gochat-logging node-exporter: image: prom/node-exporter:v1.9.1@sha256:d00a542e409ee618a4edc67da14dd48c5da66726bbd5537ab2af9c1dfc442c8a restart: always command: ["--collector.disable-defaults", "--collector.textfile", "--collector.textfile.directory=/var/lib/node_exporter/textfile_collector"] volumes: - ./data/backup-metrics:/var/lib/node_exporter/textfile_collector:ro logging: *gochat-logging cadvisor: image: gcr.io/cadvisor/cadvisor:v0.52.1@sha256:f40e65878e25c2e78ea037f73a449527a0fb994e303dc3e34cb6b187b4b91435 restart: always privileged: true devices: - /dev/kmsg:/dev/kmsg volumes: - /:/rootfs:ro - /var/run:/var/run:ro - /sys:/sys:ro - /var/lib/docker:/var/lib/docker:ro - /dev/disk:/dev/disk:ro logging: *gochat-logging alertmanager: image: prom/alertmanager:v0.28.1@sha256:27c475db5fb156cab31d5c18a4251ac7ed567746a2483ff264516437a39b15ba restart: always command: ["--config.file=/etc/alertmanager/alertmanager.yml", "--storage.path=/alertmanager"] ports: - "127.0.0.1:${ALERTMANAGER_PORT:-9093}:9093" volumes: - ../prometheus/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro - type: bind source: ${ALERTMANAGER_WEBHOOK_URL_FILE:-../../.secrets/alertmanager-webhook-url} target: /run/secrets/alertmanager-webhook-url read_only: true bind: create_host_path: false - ./data/alertmanager:/alertmanager logging: *gochat-logging prometheus: image: prom/prometheus:v3.5.0@sha256:63805ebb8d2b3920190daf1cb14a60871b16fd38bed42b857a3182bc621f4996 restart: always depends_on: - alertmanager - blackbox-exporter - cadvisor - node-exporter - postgres-exporter - redis-exporter command: ["--config.file=/etc/prometheus/prometheus.yml", "--storage.tsdb.path=/prometheus", "--storage.tsdb.retention.time=${PROMETHEUS_RETENTION:-30d}"] ports: - "127.0.0.1:${PROMETHEUS_PORT:-9090}:9090" volumes: - ../prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ../../backend/configs/prometheus_alerts.yml:/etc/prometheus/rules/gochat.yml:ro - ./data/prometheus:/prometheus logging: *gochat-logging