services: postgresql: image: bitnami/postgresql:15 container_name: discourse_postgres restart: unless-stopped volumes: - postgres_data:/bitnami/postgresql environment: - POSTGRESQL_POSTGRES_PASSWORD=${POSTGRES_ROOT_PASSWORD} - POSTGRESQL_USERNAME=${DISCOURSE_DB_USER} - POSTGRESQL_PASSWORD=${DISCOURSE_DB_PASSWORD} - POSTGRESQL_DATABASE=${DISCOURSE_DB_NAME} healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DISCOURSE_DB_USER} -d ${DISCOURSE_DB_NAME}"] interval: 15s timeout: 5s retries: 5 start_period: 30s networks: - discourse_internal redis: image: bitnami/redis:7.2 container_name: discourse_redis restart: unless-stopped volumes: - redis_data:/bitnami/redis/data environment: - REDIS_PASSWORD=${REDIS_PASSWORD} - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 15s timeout: 5s retries: 5 start_period: 15s networks: - discourse_internal discourse: image: bitnami/discourse:3 container_name: discourse_app restart: unless-stopped depends_on: postgresql: condition: service_healthy redis: condition: service_healthy volumes: - discourse_data:/bitnami/discourse environment: # --- Site --- - DISCOURSE_HOST=${DISCOURSE_HOST} - DISCOURSE_SITE_NAME=${DISCOURSE_SITE_NAME} - DISCOURSE_HTTPS=false # SSL is handled by Nginx Proxy Manager # --- Admin account (first-run only) --- - DISCOURSE_USERNAME=${DISCOURSE_ADMIN_USERNAME} - DISCOURSE_PASSWORD=${DISCOURSE_ADMIN_PASSWORD} - DISCOURSE_EMAIL=${DISCOURSE_ADMIN_EMAIL} # --- Database --- - DISCOURSE_DATABASE_HOST=postgresql - DISCOURSE_DATABASE_PORT_NUMBER=5432 - DISCOURSE_DATABASE_NAME=${DISCOURSE_DB_NAME} - DISCOURSE_DATABASE_USER=${DISCOURSE_DB_USER} - DISCOURSE_DATABASE_PASSWORD=${DISCOURSE_DB_PASSWORD} - POSTGRESQL_CLIENT_DATABASE_HOST=postgresql - POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER=5432 - POSTGRESQL_CLIENT_POSTGRES_USER=postgres - POSTGRESQL_CLIENT_POSTGRES_PASSWORD=${POSTGRES_ROOT_PASSWORD} - POSTGRESQL_CLIENT_CREATE_DATABASE_NAME=${DISCOURSE_DB_NAME} - POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME=${DISCOURSE_DB_USER} - POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD=${DISCOURSE_DB_PASSWORD} # --- Redis --- - DISCOURSE_REDIS_HOST=redis - DISCOURSE_REDIS_PORT_NUMBER=6379 - DISCOURSE_REDIS_PASSWORD=${REDIS_PASSWORD} # --- SMTP (Microsoft 365 / Outlook Business) --- - DISCOURSE_SMTP_HOST=smtp.office365.com - DISCOURSE_SMTP_PORT=587 - DISCOURSE_SMTP_USER=${SMTP_USERNAME} - DISCOURSE_SMTP_PASSWORD=${SMTP_PASSWORD} - DISCOURSE_SMTP_PROTOCOL=tls - DISCOURSE_SMTP_AUTH=login - DISCOURSE_NOTIFICATION_EMAIL=${SMTP_FROM_ADDRESS} healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:3000/ || exit 1"] interval: 30s timeout: 15s retries: 5 start_period: 120s networks: - discourse_internal - proxy # No ports exposed to host — Nginx Proxy Manager connects via the proxy network sidekiq: image: bitnami/discourse:3 container_name: discourse_sidekiq restart: unless-stopped depends_on: discourse: condition: service_healthy volumes: - discourse_data:/bitnami/discourse command: /opt/bitnami/scripts/discourse-sidekiq/run.sh environment: # Inherit the same config as the main app - DISCOURSE_HOST=${DISCOURSE_HOST} - DISCOURSE_DATABASE_HOST=postgresql - DISCOURSE_DATABASE_PORT_NUMBER=5432 - DISCOURSE_DATABASE_NAME=${DISCOURSE_DB_NAME} - DISCOURSE_DATABASE_USER=${DISCOURSE_DB_USER} - DISCOURSE_DATABASE_PASSWORD=${DISCOURSE_DB_PASSWORD} - DISCOURSE_REDIS_HOST=redis - DISCOURSE_REDIS_PORT_NUMBER=6379 - DISCOURSE_REDIS_PASSWORD=${REDIS_PASSWORD} - DISCOURSE_SMTP_HOST=smtp.office365.com - DISCOURSE_SMTP_PORT=587 - DISCOURSE_SMTP_USER=${SMTP_USERNAME} - DISCOURSE_SMTP_PASSWORD=${SMTP_PASSWORD} - DISCOURSE_SMTP_PROTOCOL=tls - DISCOURSE_SMTP_AUTH=login - DISCOURSE_NOTIFICATION_EMAIL=${SMTP_FROM_ADDRESS} networks: - discourse_internal volumes: postgres_data: driver: local redis_data: driver: local discourse_data: driver: local networks: discourse_internal: driver: bridge internal: true # Postgres and Redis are not reachable from outside the stack proxy: external: true # Must match the network name used by your NPM stack