chore(infra): Finalize local docker stack (Monitoring, Frontends, Fixes)
This commit is contained in:
@@ -47,6 +47,13 @@ PGADMIN_EMAIL=meldestelle@mo-code.at
|
|||||||
PGADMIN_PASSWORD=pgadmin
|
PGADMIN_PASSWORD=pgadmin
|
||||||
PGADMIN_PORT=8888:80
|
PGADMIN_PORT=8888:80
|
||||||
|
|
||||||
|
# --- POSTGRES-EXPORTER ---
|
||||||
|
POSTGRES_EXPORTER_IMAGE=prometheuscommunity/postgres-exporter:v0.18.0
|
||||||
|
|
||||||
|
# --- ALERTMANAGER ---
|
||||||
|
ALERTMANAGER_IMAGE=prom/alertmanager:v0.29.0
|
||||||
|
ALERTMANAGER_PORT=9093:9093
|
||||||
|
|
||||||
# --- PROMETHEUS ---
|
# --- PROMETHEUS ---
|
||||||
PROMETHEUS_IMAGE=prom/prometheus:v3.7.3
|
PROMETHEUS_IMAGE=prom/prometheus:v3.7.3
|
||||||
PROMETHEUS_PORT=9090:9090
|
PROMETHEUS_PORT=9090:9090
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
# Meldestelle
|
# Meldestelle
|
||||||
|
|
||||||
|
|
||||||
> Modulares System für Pferdesportveranstaltungen mit Domain-Driven Design
|
> Modulares System für Pferdesportveranstaltungen mit Domain-Driven Design
|
||||||
|
|
||||||
[](https://github.com/StefanMoCoAt/meldestelle/actions)
|
[](https://github.com/StefanMoCoAt/meldestelle/actions)
|
||||||
|
|||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
# ==========================================
|
||||||
|
# Meldestelle - Docker Compose Environment
|
||||||
|
# Single Source of Truth (SSoT)
|
||||||
|
# ==========================================
|
||||||
|
# Profil: DEVELOPMENT (Lokal)
|
||||||
|
|
||||||
|
# --- PROJEKT EINSTELLUNGEN ---
|
||||||
|
PROJECT_NAME=meldestelle
|
||||||
|
PROJEKT_EMAIL=meldestelle@mo-code.at
|
||||||
|
# Restart Policy: 'no' für Dev (Fehler sehen), 'always' für Prod
|
||||||
|
RESTART_POLICY=no
|
||||||
|
|
||||||
|
# --- POSTGRESQL (Datenbank) ---
|
||||||
|
POSTGRES_USER=pg-user
|
||||||
|
POSTGRES_PASSWORD=pg-password
|
||||||
|
POSTGRES_PORT=5432:5432
|
||||||
|
# Standard-Datenbankname für lokale Entwicklung (sollte mit docker-compose übereinstimmen)
|
||||||
|
POSTGRES_DB=pg-meldestelle-db
|
||||||
|
|
||||||
|
# --- REDIS (Cache) ---
|
||||||
|
# Optional: Redis Passwort setzen. Leer lassen = kein Passwort.
|
||||||
|
# Wenn gesetzt, muss der Healthcheck in docker-compose das berücksichtigen.
|
||||||
|
REDIS_PORT=6379:6379
|
||||||
|
REDIS_PASSWORD=
|
||||||
|
|
||||||
|
# --- KEYCLOAK (Identity Provider) ---
|
||||||
|
KC_ADMIN_USER=kc-admin
|
||||||
|
KC_ADMIN_PASSWORD=kc-password
|
||||||
|
KC_HOSTNAME=localhost
|
||||||
|
KC_PORT=8180:8080
|
||||||
|
|
||||||
|
# --- PGADMIN (DB GUI) ---
|
||||||
|
PGADMIN_EMAIL=meldestelle@mo-code.at
|
||||||
|
PGADMIN_PASSWORD=strong-password
|
||||||
|
PGADMIN_PORT=8888:80
|
||||||
|
|
||||||
|
# --- PROMETHEUS (Metriken) ---
|
||||||
|
PROMETHEUS_PORT=9090:9090
|
||||||
|
|
||||||
|
# --- GRAFANA (Monitoring GUI) ---
|
||||||
|
GF_ADMIN_USER=gf-admin
|
||||||
|
GF_ADMIN_PASSWORD=gf-password
|
||||||
|
GF_PORT=3000:3000
|
||||||
|
|
||||||
|
# --- SERVICE DISCOVERY (Consul) ---
|
||||||
|
CONSUL_PORT=8500:8500
|
||||||
|
CONSUL_UDP_PORT=8600:8600
|
||||||
|
|
||||||
|
# --- API GATEWAY ---
|
||||||
|
GATEWAY_SERVER_PORT=8081:8081
|
||||||
|
GATEWAY_DEBUG_PORT=5005:5005
|
||||||
|
|
||||||
|
# --- MICROSERVICES ---
|
||||||
|
PING_PORT=8082:8082
|
||||||
|
PING_DEBUG_PORT=5006:5006
|
||||||
|
|
||||||
|
# --- WEB CLIENTS ---
|
||||||
|
# Web-App (Nginx inside container listens on 80)
|
||||||
|
WEB_APP_PORT=4000:4000
|
||||||
|
|
||||||
|
# Desktop-App (VNC + noVNC)
|
||||||
|
DESKTOP_APP_VNC_PORT=5901:5901
|
||||||
|
DESKTOP_APP_NOVNC_PORT=6080:6080
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
global:
|
||||||
|
resolve_timeout: 5m
|
||||||
|
# FIX: Hier müssen echte Werte stehen, keine Variablen!
|
||||||
|
# Wenn du noch keinen SMTP hast, trag Dummy-Werte ein, damit der Container startet.
|
||||||
|
smtp_smarthost: 'smtp.gmail.com:587'
|
||||||
|
smtp_from: 'alertmanager@meldestelle.at'
|
||||||
|
smtp_auth_username: 'deine-email@gmail.com'
|
||||||
|
smtp_auth_password: 'dein-passwort'
|
||||||
|
smtp_require_tls: true
|
||||||
|
|
||||||
|
route:
|
||||||
|
receiver: 'email-notifications'
|
||||||
|
# ... (Rest bleibt gleich)
|
||||||
|
|
||||||
|
receivers:
|
||||||
|
- name: 'email-notifications'
|
||||||
|
email_configs:
|
||||||
|
- to: 'admin@meldestelle.at'
|
||||||
|
send_resolved: true
|
||||||
|
|
||||||
|
- name: 'slack-critical'
|
||||||
|
slack_configs:
|
||||||
|
# FIX: Auch hier die echte Webhook URL eintragen oder den Block entfernen, wenn nicht genutzt
|
||||||
|
- api_url: 'https://hooks.slack.com/services/example'
|
||||||
|
channel: '#alerts-critical'
|
||||||
|
# ...
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
global:
|
|
||||||
resolve_timeout: 5m
|
|
||||||
# SMTP configuration for email alerts - use environment variables
|
|
||||||
smtp_smarthost: '${SMTP_SMARTHOST:-smtp.example.com:587}'
|
|
||||||
smtp_from: '${SMTP_FROM:-alertmanager@meldestelle.at}'
|
|
||||||
smtp_auth_username: '${SMTP_AUTH_USERNAME:-alertmanager@meldestelle.at}'
|
|
||||||
smtp_auth_password: '${SMTP_AUTH_PASSWORD}'
|
|
||||||
smtp_require_tls: true
|
|
||||||
|
|
||||||
# The root route on which each incoming alert enters.
|
|
||||||
route:
|
|
||||||
# The root route must not have any matchers as it is the entry point for all alerts
|
|
||||||
# The default receiver is the one that handles alerts that don't match any of the specific routes
|
|
||||||
receiver: 'email-notifications'
|
|
||||||
|
|
||||||
# How long to wait before sending a notification again if it has already been sent successfully
|
|
||||||
repeat_interval: 4h
|
|
||||||
|
|
||||||
# How long to initially wait to send a notification for a group of alerts
|
|
||||||
group_wait: 30s
|
|
||||||
|
|
||||||
# How long to wait before sending a notification about new alerts that are added to a group
|
|
||||||
group_interval: 5m
|
|
||||||
|
|
||||||
# A default grouping of alerts
|
|
||||||
group_by: ['alertname', 'cluster', 'service']
|
|
||||||
|
|
||||||
# Child routes for specific alert categories
|
|
||||||
routes:
|
|
||||||
- receiver: 'slack-critical'
|
|
||||||
matchers:
|
|
||||||
- severity="critical"
|
|
||||||
repeat_interval: 1h
|
|
||||||
|
|
||||||
- receiver: 'slack-warnings'
|
|
||||||
matchers:
|
|
||||||
- severity="warning"
|
|
||||||
repeat_interval: 12h
|
|
||||||
|
|
||||||
# Inhibition rules allow to mute a set of alerts given that another alert is firing
|
|
||||||
inhibit_rules:
|
|
||||||
- source_matchers:
|
|
||||||
- severity="critical"
|
|
||||||
target_matchers:
|
|
||||||
- severity="warning"
|
|
||||||
# Apply inhibition if the alertname is the same
|
|
||||||
equal: ['alertname', 'cluster', 'service']
|
|
||||||
|
|
||||||
# Receivers define notification integrations
|
|
||||||
receivers:
|
|
||||||
- name: 'email-notifications'
|
|
||||||
email_configs:
|
|
||||||
- to: 'admin@meldestelle.at'
|
|
||||||
send_resolved: true
|
|
||||||
|
|
||||||
- name: 'slack-critical'
|
|
||||||
slack_configs:
|
|
||||||
- api_url: '${SLACK_WEBHOOK_URL_CRITICAL}'
|
|
||||||
channel: '${SLACK_CHANNEL_CRITICAL:-#alerts-critical}'
|
|
||||||
send_resolved: true
|
|
||||||
title: '{{ .CommonAnnotations.summary }}'
|
|
||||||
text: >-
|
|
||||||
{{ range .Alerts }}
|
|
||||||
*Alert:* {{ .Annotations.summary }}
|
|
||||||
*Description:* {{ .Annotations.description }}
|
|
||||||
*Severity:* {{ .Labels.severity }}
|
|
||||||
*Instance:* {{ .Labels.instance }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
- name: 'slack-warnings'
|
|
||||||
slack_configs:
|
|
||||||
- api_url: '${SLACK_WEBHOOK_URL_WARNINGS}'
|
|
||||||
channel: '${SLACK_CHANNEL_WARNINGS:-#alerts-warnings}'
|
|
||||||
send_resolved: true
|
|
||||||
title: '{{ .CommonAnnotations.summary }}'
|
|
||||||
text: >-
|
|
||||||
{{ range .Alerts }}
|
|
||||||
*Alert:* {{ .Annotations.summary }}
|
|
||||||
*Description:* {{ .Annotations.description }}
|
|
||||||
*Severity:* {{ .Labels.severity }}
|
|
||||||
*Instance:* {{ .Labels.instance }}
|
|
||||||
{{ end }}
|
|
||||||
@@ -11,10 +11,10 @@ global:
|
|||||||
alerting:
|
alerting:
|
||||||
alertmanagers:
|
alertmanagers:
|
||||||
- static_configs:
|
- static_configs:
|
||||||
- targets:
|
- targets:
|
||||||
# Da wir Alertmanager noch nicht im Docker Compose haben (kommt noch!),
|
# Da wir Alertmanager noch nicht im Docker Compose haben (kommt noch!),
|
||||||
# lassen wir das vorerst auskommentiert oder fügen den Container hinzu.
|
# lassen wir das vorerst auskommentiert oder fügen den Container hinzu.
|
||||||
- "alertmanager:9093"
|
- "alertmanager:9093"
|
||||||
|
|
||||||
rule_files:
|
rule_files:
|
||||||
- "/etc/prometheus/rules/alerts.yaml"
|
- "/etc/prometheus/rules/alerts.yaml"
|
||||||
@@ -61,3 +61,8 @@ scrape_configs:
|
|||||||
- source_labels: [ __meta_consul_address, __meta_consul_service_port ]
|
- source_labels: [ __meta_consul_address, __meta_consul_service_port ]
|
||||||
separator: ':'
|
separator: ':'
|
||||||
target_label: instance
|
target_label: instance
|
||||||
|
|
||||||
|
# Job 4: Postgres Exporter (Statisch, da kein Consul-Client im Image)
|
||||||
|
- job_name: 'postgres-exporter'
|
||||||
|
static_configs:
|
||||||
|
- targets: [ 'postgres-exporter:9187' ]
|
||||||
|
|||||||
@@ -267,4 +267,3 @@ Implementieren Sie Überwachung für:
|
|||||||
|
|
||||||
**Letzte Aktualisierung**: 25. Juli 2025
|
**Letzte Aktualisierung**: 25. Juli 2025
|
||||||
|
|
||||||
Für weitere Informationen zur Produktionsumgebung siehe [README-PRODUCTION.md](../../Tagebuch/README-PRODUCTION.md).
|
|
||||||
|
|||||||
+14
-13
@@ -119,37 +119,37 @@ services:
|
|||||||
|
|
||||||
# --- MONITORING: Postgres Exporter ---
|
# --- MONITORING: Postgres Exporter ---
|
||||||
postgres-exporter:
|
postgres-exporter:
|
||||||
image: quay.io/prometheuscommunity/postgres-exporter
|
image: "${POSTGRES_EXPORTER_IMAGE:-prometheuscommunity/postgres-exporter:v0.18.0}"
|
||||||
container_name: "${PROJECT_NAME:-meldestelle}-postgres-exporter"
|
container_name: "${PROJECT_NAME:-meldestelle}-postgres-exporter"
|
||||||
restart: unless-stopped
|
restart: "${RESTART_POLICY:-no}"
|
||||||
environment:
|
environment:
|
||||||
DATA_SOURCE_NAME: "postgresql://pg-user:pg-password@postgres:5432/pg-meldestelle-db?sslmode=disable"
|
DATA_SOURCE_NAME: "postgresql://${POSTGRES_USER:-pg-user}:${POSTGRES_PASSWORD:-pg-password}@postgres:5432/${POSTGRES_DB:-pg-meldestelle-db}?sslmode=disable"
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: "service_healthy"
|
||||||
networks:
|
networks:
|
||||||
meldestelle-network:
|
meldestelle-network:
|
||||||
aliases:
|
aliases:
|
||||||
- postgres-exporter
|
- "postgres-exporter"
|
||||||
|
|
||||||
# --- MONITORING: Alertmanager ---
|
# --- MONITORING: Alertmanager ---
|
||||||
alertmanager:
|
alertmanager:
|
||||||
image: prom/alertmanager:v0.26.0
|
image: "${ALERTMANAGER_IMAGE:-prom/alertmanager:v0.29.0}"
|
||||||
container_name: "${PROJECT_NAME:-meldestelle}-alertmanager"
|
container_name: "${PROJECT_NAME:-meldestelle}-alertmanager"
|
||||||
restart: unless-stopped
|
restart: "${RESTART_POLICY:-no}"
|
||||||
ports:
|
ports:
|
||||||
- "9093:9093"
|
- "${ALERTMANAGER_PORT:-9093:9093}"
|
||||||
volumes:
|
volumes:
|
||||||
# Wir müssen hier envsubst nutzen ODER die Config ohne Variablen schreiben.
|
# Wir müssen hier envsubst nutzen ODER die Config ohne Variablen schreiben.
|
||||||
# Einfachste Lösung: Ein Entrypoint-Script, das envsubst macht (ähnlich wie bei Nginx).
|
# Einfachste Lösung: Ein Entrypoint-Script, das envsubst macht (ähnlich wie bei Nginx).
|
||||||
# ODER: Wir hardcoden es für Dev erst mal.
|
# ODER: Wir hardcoden es für Dev erst mal.
|
||||||
- ./config/backend/infrastructure/monitoring/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml
|
- ./config/backend/infrastructure/monitoring/alertmanager/alertmanager.yaml:/etc/alertmanager/alertmanager.yaml
|
||||||
command:
|
command:
|
||||||
- --config.file=/etc/alertmanager/alertmanager.yml
|
- --config.file=/etc/alertmanager/alertmanager.yaml
|
||||||
networks:
|
networks:
|
||||||
meldestelle-network:
|
meldestelle-network:
|
||||||
aliases:
|
aliases:
|
||||||
- alertmanager
|
- "alertmanager"
|
||||||
|
|
||||||
# --- MONITORING: Prometheus ---
|
# --- MONITORING: Prometheus ---
|
||||||
prometheus:
|
prometheus:
|
||||||
@@ -161,6 +161,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- "prometheus-data:/prometheus"
|
- "prometheus-data:/prometheus"
|
||||||
- "./config/backend/infrastructure/monitoring/prometheus:/etc/prometheus:Z"
|
- "./config/backend/infrastructure/monitoring/prometheus:/etc/prometheus:Z"
|
||||||
|
- "./config/backend/infrastructure/monitoring/prometheus/rules:/etc/prometheus/rules:Z"
|
||||||
command:
|
command:
|
||||||
- --web.enable-lifecycle
|
- --web.enable-lifecycle
|
||||||
- --config.file=/etc/prometheus/prometheus.yaml
|
- --config.file=/etc/prometheus/prometheus.yaml
|
||||||
@@ -189,9 +190,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
# Provisioning (datasources/dashboards) from central config
|
# Provisioning (datasources/dashboards) from central config
|
||||||
- ../config/backend/infrastructure/monitoring/grafana/provisioning:/etc/grafana/provisioning:Z
|
- ./config/backend/infrastructure/monitoring/grafana/provisioning:/etc/grafana/provisioning:Z
|
||||||
# Dashboards directory (referenced by a provisioning file path: /var/lib/grafana/dashboards)
|
# Dashboards directory (referenced by a provisioning file path: /var/lib/grafana/dashboards)
|
||||||
- ../config/backend/infrastructure/monitoring/grafana/dashboards:/var/lib/grafana/dashboards:Z
|
- ./config/backend/infrastructure/monitoring/grafana/dashboards:/var/lib/grafana/dashboards:Z
|
||||||
depends_on:
|
depends_on:
|
||||||
prometheus:
|
prometheus:
|
||||||
condition: "service_healthy"
|
condition: "service_healthy"
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ fun main() {
|
|||||||
try {
|
try {
|
||||||
console.log("[WebApp] startApp(): readyState=", document.asDynamic().readyState)
|
console.log("[WebApp] startApp(): readyState=", document.asDynamic().readyState)
|
||||||
val root = document.getElementById("ComposeTarget") as HTMLElement
|
val root = document.getElementById("ComposeTarget") as HTMLElement
|
||||||
console.log("[WebApp] ComposeTarget exists? ", (root != null))
|
console.log("[WebApp] ComposeTarget exists? ", (true))
|
||||||
ComposeViewport(root) {
|
ComposeViewport(root) {
|
||||||
MainApp()
|
MainApp()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user