services: # ── OpenTelemetry Collector ── otel-collector: container_name: otel-collector image: otel/opentelemetry-collector-contrib:latest restart: always networks: app-shared-net: aliases: - otel-collector ports: - '4317:4317' # OTLP gRPC - '4318:4318' # OTLP HTTP - '8889:8889' # Prometheus metrics command: - '--config=/etc/otel/config.yml' volumes: - ../../infra/otel/otel-collector-config.yml:/etc/otel/config.yml:ro depends_on: jaeger: condition: service_started # ── Jaeger (Tracing Backend + Built-in UI) ── jaeger: container_name: jaeger image: jaegertracing/all-in-one:latest restart: always networks: app-shared-net: aliases: - jaeger ports: - '16686:16686' # Jaeger UI + API environment: - COLLECTOR_OTLP_ENABLED=true - COLLECTOR_ZIPKIN_HOST_PORT=:9411 - METRICS_STORAGE_TYPE=prometheus - PROMETHEUS_SERVER_URL=http://otel-collector:8889 - LOG_LEVEL=info # ── Custom Dashboard (nginx:alpine) ── dashboard: container_name: dashboard build: context: ../.. dockerfile: infra/docker/dashboard.Dockerfile restart: always networks: app-shared-net: aliases: - dashboard ports: - '8080:8080' networks: app-shared-net: name: app-shared-net external: true