Ctrl K
ComunidadGuías…

docker-compose.dev.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Guardyn Development Environment
# Start: docker compose -f docker-compose.dev.yml up -d
# Logs:  docker compose -f docker-compose.dev.yml logs -f <service>
# Stop:  docker compose -f docker-compose.dev.yml down
# Reset: docker compose -f docker-compose.dev.yml down -v
#
# E2EE is not configurable. The server never sees plaintext, in development as in
# production - it relays opaque bytes (docs/adr/ADR-0010-pure-relay-server.md). There is no
# switch to make debugging easier, because a switch is what invariant I-2 forbids.

version: "3.9"

x-rust-service: &rust-service
  build:
    context: ./backend
    dockerfile: Dockerfile.dev
  volumes:
    - ./backend:/app
    - cargo_cache:/usr/local/cargo/registry
    - cargo_git:/usr/local/cargo/git
    - target_cache:/app/target
  environment: &rust-env
    RUST_LOG: debug
    RUST_BACKTRACE: 1
    # JWT authentication (use GUARDYN_ prefix for consistency)
    GUARDYN_AUTH__JWT_SECRET: "UNSAFE_DEV_SECRET_CHANGE_IN_PRODUCTION_32BYTES"
    SCYLLA_CONSISTENCY: one

services:
  # ═══════════════════════════════════════════════════════════════
  # DATA LAYER
  # ═══════════════════════════════════════════════════════════════

  # NATS JetStream for real-time messaging
  nats:
    image: nats:2.10-alpine
    container_name: guardyn-nats
    command: ["-js", "-m", "8222"]
    ports:
      - "4222:4222"      # Client connections
      - "8222:8222"      # HTTP monitoring
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost:8222/healthz"]
      interval: 10s
      timeout: 5s
      retries: 5

  redpanda:
    image: redpandadata/redpanda:v24.2.1
    container_name: guardyn-redpanda
    command:
      - redpanda start
      - --mode dev-container
      - --smp 1
      - --memory 512M
      - --overprovisioned
      - --kafka-addr internal://0.0.0.0:9092,external://0.0.0.0:19092
      - --advertise-kafka-addr internal://redpanda:9092,external://localhost:19092
      - --schema-registry-addr internal://0.0.0.0:8081,external://0.0.0.0:18081
      - --rpc-addr redpanda:33145
      - --advertise-rpc-addr redpanda:33145
    ports:
      - "19092:19092"    # Kafka API (external)
      - "18081:18081"    # Schema Registry (external)
      - "8082:8082"      # REST Proxy
      - "9644:9644"      # Admin API
    volumes:
      - redpanda_data:/var/lib/redpanda/data
    healthcheck:
      test: ["CMD", "rpk", "cluster", "health"]
      interval: 10s
      timeout: 5s
      retries: 5

  # PD (Placement Driver) for TiKV
  pd:
    image: pingcap/pd:v7.5.0
    container_name: guardyn-pd
    command:
      - --name=pd
      - --client-urls=http://0.0.0.0:2379
      - --peer-urls=http://0.0.0.0:2380
      - --advertise-client-urls=http://pd:2379
      - --advertise-peer-urls=http://pd:2380
      - --data-dir=/data/pd
    ports:
      - "2379:2379"
    volumes:
      - pd_data:/data/pd
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:2379/health"]
      interval: 10s
      timeout: 5s
      retries: 5

  tikv:
    image: pingcap/tikv:v7.5.0
    container_name: guardyn-tikv
    command:
      - --pd-endpoints=pd:2379
      - --addr=0.0.0.0:20160
      - --advertise-addr=tikv:20160
      - --data-dir=/data/tikv
    ports:
      - "20160:20160"
    volumes:
      - tikv_data:/data/tikv
    depends_on:
      pd:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:20180/metrics"]
      interval: 10s
      timeout: 5s
      retries: 5

  scylladb:
    image: scylladb/scylla:5.4
    container_name: guardyn-scylladb
    command: --smp 1 --memory 512M --developer-mode 1 --api-address 0.0.0.0
    ports:
      - "9042:9042"      # CQL
      - "10000:10000"    # REST API
    volumes:
      - scylla_data:/var/lib/scylla
    healthcheck:
      test: ["CMD", "cqlsh", "-e", "SELECT now() FROM system.local"]
      interval: 10s
      timeout: 10s
      retries: 10

  minio:
    image: minio/minio:latest
    container_name: guardyn-minio
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: guardyn
      MINIO_ROOT_PASSWORD: guardyn-dev-secret
    ports:
      - "9000:9000"      # S3 API
      - "9001:9001"      # Console
    volumes:
      - minio_data:/data
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 10s
      timeout: 5s
      retries: 5

  # MinIO initial bucket setup
  minio-init:
    image: minio/mc:latest
    container_name: guardyn-minio-init
    depends_on:
      minio:
        condition: service_healthy
    entrypoint: >
      /bin/sh -c "
      mc alias set myminio http://minio:9000 guardyn guardyn-dev-secret;
      mc mb myminio/guardyn-media --ignore-existing;
      mc mb myminio/guardyn-avatars --ignore-existing;
      mc anonymous set download myminio/guardyn-avatars;
      echo 'MinIO buckets initialized';
      exit 0;
      "

  # ═══════════════════════════════════════════════════════════════
  # EDGE LAYER
  # ═══════════════════════════════════════════════════════════════

  envoy:
    image: envoyproxy/envoy:v1.31-latest
    container_name: guardyn-envoy
    volumes:
      - ./infra/envoy/envoy-dev.yaml:/etc/envoy/envoy.yaml:ro
    ports:
      - "8080:8080"      # API Gateway (gRPC routing)
      - "8443:8443"      # API Gateway TLS (if needed)
      - "9901:9901"      # Admin
    depends_on:
      - auth-service
      - messaging-service
      - presence-service
      - media-service
      - call-service
    healthcheck:
      test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/9901' || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 5s

  # ═══════════════════════════════════════════════════════════════
  # BACKEND SERVICES (with hot reload via cargo-watch)
  # ═══════════════════════════════════════════════════════════════

  auth-service:
    <<: *rust-service
    container_name: guardyn-auth
    command: cargo watch -x 'run --bin auth-service'
    environment:
      <<: *rust-env
      GUARDYN_SERVICE_NAME: auth-service
      GUARDYN_HOST: "0.0.0.0"
      GUARDYN_PORT: "50051"
      GUARDYN_DATABASE__TIKV_PD_ENDPOINTS: pd:2379
      GUARDYN_DATABASE__SCYLLADB_NODES: scylladb:9042
      GUARDYN_MESSAGING__NATS_URL: nats://nats:4222
      # Redpanda's internal listener. localhost:19092 is the external listener, reachable
      # only from the host - inside a container it resolves to the container itself.
      REDPANDA_BROKERS: redpanda:9092
      GUARDYN_OBSERVABILITY__OTLP_ENDPOINT: ""
      GUARDYN_OBSERVABILITY__LOG_LEVEL: debug
    ports:
      - "50051:50051"
    depends_on:
      pd:
        condition: service_healthy
      tikv:
        condition: service_started
      redpanda:
        condition: service_healthy

  messaging-service:
    <<: *rust-service
    container_name: guardyn-messaging
    command: cargo watch -x 'run --bin guardyn-messaging-service'
    environment:
      <<: *rust-env
      GUARDYN_SERVICE_NAME: messaging-service
      GUARDYN_HOST: "0.0.0.0"
      GUARDYN_PORT: "50052"
      WEBSOCKET_PORT: "8081"
      GUARDYN_DATABASE__TIKV_PD_ENDPOINTS: pd:2379
      GUARDYN_DATABASE__SCYLLADB_NODES: scylladb:9042
      GUARDYN_MESSAGING__NATS_URL: nats://nats:4222
      # Consumed by event_consumer.rs; see the note on auth-service.
      REDPANDA_BROKERS: redpanda:9092
      GUARDYN_OBSERVABILITY__OTLP_ENDPOINT: ""
      GUARDYN_OBSERVABILITY__LOG_LEVEL: debug
    ports:
      - "50052:50052"
      - "8081:8081"      # WebSocket
    depends_on:
      pd:
        condition: service_healthy
      tikv:
        condition: service_started
      scylladb:
        condition: service_healthy
      nats:
        condition: service_healthy
      redpanda:
        condition: service_healthy

  presence-service:
    <<: *rust-service
    container_name: guardyn-presence
    command: cargo watch -x 'run --bin guardyn-presence-service'
    environment:
      <<: *rust-env
      GUARDYN_SERVICE_NAME: presence-service
      GUARDYN_HOST: "0.0.0.0"
      GUARDYN_PORT: "50053"
      GUARDYN_DATABASE__TIKV_PD_ENDPOINTS: pd:2379
      GUARDYN_DATABASE__SCYLLADB_NODES: scylladb:9042
      GUARDYN_MESSAGING__NATS_URL: nats://nats:4222
      GUARDYN_OBSERVABILITY__OTLP_ENDPOINT: ""
      GUARDYN_OBSERVABILITY__LOG_LEVEL: debug
    ports:
      - "50053:50053"
    depends_on:
      pd:
        condition: service_healthy
      nats:
        condition: service_healthy

  media-service:
    <<: *rust-service
    container_name: guardyn-media
    command: cargo watch -x 'run --bin guardyn-media-service'
    environment:
      <<: *rust-env
      GUARDYN_SERVICE_NAME: media-service
      GUARDYN_HOST: "0.0.0.0"
      GUARDYN_PORT: "50054"
      # S3/MinIO configuration (MediaConfig::from_env() uses these)
      S3_ENDPOINT: http://minio:9000
      # Public endpoint for presigned URLs - use 10.0.2.2 for Android emulator
      # This is the special IP that Android emulator uses to reach host machine
      # The presigned URL signature MUST match the actual host the client connects to
      S3_PUBLIC_ENDPOINT: http://10.0.2.2:9000
      S3_ACCESS_KEY: guardyn
      S3_SECRET_KEY: guardyn-dev-secret
      S3_BUCKET_NAME: guardyn-media
      S3_REGION: us-east-1
      AWS_ACCESS_KEY_ID: guardyn
      AWS_SECRET_ACCESS_KEY: guardyn-dev-secret
      # TiKV configuration (code uses TIKV_PD_ENDPOINTS)
      TIKV_PD_ENDPOINTS: pd:2379
      GUARDYN_DATABASE__TIKV_PD_ENDPOINTS: pd:2379
      GUARDYN_DATABASE__SCYLLADB_NODES: scylladb:9042
      GUARDYN_MESSAGING__NATS_URL: nats://nats:4222
      GUARDYN_OBSERVABILITY__OTLP_ENDPOINT: ""
      GUARDYN_OBSERVABILITY__LOG_LEVEL: debug
    ports:
      - "50054:50054"
    depends_on:
      minio:
        condition: service_healthy
      scylladb:
        condition: service_healthy
      pd:
        condition: service_healthy

  call-service:
    <<: *rust-service
    container_name: guardyn-call
    command: cargo watch -x 'run --bin guardyn-call-service'
    environment:
      <<: *rust-env
      GUARDYN_SERVICE_NAME: call-service
      LISTEN_ADDR: "0.0.0.0:50056"
      SCYLLA_HOSTS: scylladb:9042
      NATS_URL: nats://nats:4222
      AUTH_SERVICE_URL: http://auth-service:50051
      JWT_SECRET: "UNSAFE_DEV_SECRET_CHANGE_IN_PRODUCTION_32BYTES"
      # WebSocket signaling port
      SIGNALING_PORT: "8085"
      # ICE servers for WebRTC (STUN/TURN)
      # TURN_SERVER_URL: "turn:turn.yourdomain.com:3478"
      # TURN_USERNAME: "turnuser"
      # TURN_CREDENTIAL: "turnpass"
    ports:
      - "50056:50056"  # gRPC
      - "8085:8085"    # WebSocket signaling
    depends_on:
      pd:
        condition: service_healthy
      scylladb:
        condition: service_healthy
      nats:
        condition: service_healthy
      auth-service:
        condition: service_started

  notification-service:
    <<: *rust-service
    container_name: guardyn-notification
    command: cargo watch -x 'run --bin guardyn-notification-service'
    environment:
      <<: *rust-env
      GUARDYN_SERVICE_NAME: notification-service
      GUARDYN_HOST: "0.0.0.0"
      GUARDYN_PORT: "50055"
      GUARDYN_DATABASE__TIKV_PD_ENDPOINTS: pd:2379
      GUARDYN_DATABASE__SCYLLADB_NODES: scylladb:9042
      GUARDYN_MESSAGING__NATS_URL: nats://nats:4222
      GUARDYN_OBSERVABILITY__OTLP_ENDPOINT: ""
      GUARDYN_OBSERVABILITY__LOG_LEVEL: debug
      # This service does not use the GUARDYN_* config loader - main.rs reads these two
      # directly. Without them it binds 50054 and dials the Kubernetes ScyllaDB FQDN,
      # which is why it failed to start under Compose.
      LISTEN_ADDR: "0.0.0.0:50055"
      SCYLLA_HOSTS: scylladb:9042
    ports:
      - "50055:50055"
    depends_on:
      pd:
        condition: service_healthy
      nats:
        condition: service_healthy
      scylladb:
        condition: service_healthy

  # ═══════════════════════════════════════════════════════════════
  # OBSERVABILITY (optional - uncomment if needed)
  # ═══════════════════════════════════════════════════════════════

  # prometheus:
  #   image: prom/prometheus:v2.47.0
  #   container_name: guardyn-prometheus
  #   volumes:
  #     - ./infra/observability/prometheus.yml:/etc/prometheus/prometheus.yml:ro
  #   ports:
  #     - "9090:9090"
  #   command:
  #     - '--config.file=/etc/prometheus/prometheus.yml'
  #     - '--storage.tsdb.path=/prometheus'

  # grafana:
  #   image: grafana/grafana:10.1.0
  #   container_name: guardyn-grafana
  #   environment:
  #     GF_SECURITY_ADMIN_PASSWORD: guardyn
  #     GF_AUTH_ANONYMOUS_ENABLED: "true"
  #   ports:
  #     - "3000:3000"
  #   volumes:
  #     - grafana_data:/var/lib/grafana

  # ═══════════════════════════════════════════════════════════════
  # REDPANDA CONSOLE (optional - for debugging)
  # ═══════════════════════════════════════════════════════════════

  redpanda-console:
    image: redpandadata/console:v2.7.0
    container_name: guardyn-redpanda-console
    entrypoint: /bin/sh
    command: -c "echo \"$$CONSOLE_CONFIG_FILE\" > /tmp/config.yml; /app/console"
    environment:
      CONFIG_FILEPATH: /tmp/config.yml
      CONSOLE_CONFIG_FILE: |
        kafka:
          brokers: ["redpanda:9092"]
          schemaRegistry:
            enabled: true
            urls: ["http://redpanda:8081"]
        redpanda:
          adminApi:
            enabled: true
            urls: ["http://redpanda:9644"]
    ports:
      - "8088:8080"
    depends_on:
      redpanda:
        condition: service_healthy

volumes:
  redpanda_data:
  pd_data:
  tikv_data:
  scylla_data:
  minio_data:
  cargo_cache:
  cargo_git:
  target_cache:
  # grafana_data:

networks:
  default:
    name: guardyn-dev