Ctrl K
ComunidadGuías…

docker-compose-primary-secondaries.yml

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

Archivo original ↗Preguntar a KiBot
# =============================================================================
# docker-compose-primary-secondaries.yml - full demo stack with 1 PowerDNS
# Primary + 3 PowerDNS Secondaries.
#
# Showcases the app's sync-state surface end-to-end: writes go to the Primary,
# PDNS' built-in NOTIFY + AXFR replicates each zone to every Secondary, and
# the app's per-secondary "in-sync / lagging" probe lights up green once the
# Secondaries catch up.
#
# Design:
#   * Plain `powerdns/pdns-auth:latest` for every PDNS container - no custom
#     image, no Dockerfile in this stack.
#   * Each container mounts a role-specific conf from `docker/pdns/*.conf`
#     and the gsqlite3 schema from `docker/pdns/schema.sqlite3.sql`.
#   * A tiny init container per PDNS role uses `alpine` + `sqlite3` to
#     apply the schema (and, for Secondaries, insert the supermaster row).
#     Main container depends on `service_completed_successfully`.
#   * Static IPs on a /24 so the Primary's `also-notify` + each Secondary's
#     `supermasters` row can use literal IPs - PDNS doesn't accept CIDRs
#     in those positions.
#
# Usage:
#   cp .env.example .env
#   # fill in APP_SECRET_KEY + APP_ENCRYPTION_KEY
#   docker compose -f docker-compose-primary-secondaries.yml up -d
#   # app                → http://localhost:3000
#   # Primary API        → http://localhost:8081  (X-API-Key: primary-changeme)
#   # Secondary APIs     → http://localhost:8082, :8083, :8084
# =============================================================================

networks:
  pdnsnet:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/24

name: powerdns-authadmin-primary-secondaries

services:
  # ---- PostgreSQL + Redis (app side) -----------------------------------
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: pdns
      POSTGRES_PASSWORD: pdns
      POSTGRES_DB: powerdns_authadmin
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - pdnsnet
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U pdns -d powerdns_authadmin"]
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: ["redis-server", "--appendonly", "yes"]
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - pdnsnet
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 10

  # ---- PDNS Primary ----------------------------------------------------
  pdns-primary-init:
    image: alpine:3.20
    restart: "no"
    command:
      - sh
      - -c
      - |
        set -eu
        apk add --no-cache sqlite >/dev/null
        sh /init.sh
        chown -R 953:953 /var/lib/powerdns
        chmod -R u+rwX /var/lib/powerdns
    environment:
      DB: /var/lib/powerdns/pdns.sqlite
      SCHEMA: /schema.sqlite3.sql
    volumes:
      - primary-data:/var/lib/powerdns
      - ./docker/pdns/init-primary.sh:/init.sh:ro
      - ./docker/pdns/schema.sqlite3.sql:/schema.sqlite3.sql:ro
    networks:
      - pdnsnet

  pdns-primary:
    image: powerdns/pdns-auth-49:latest
    restart: unless-stopped
    depends_on:
      pdns-primary-init:
        condition: service_completed_successfully
    ports:
      - "5300:53"
      - "5300:53/udp"
      - "8081:8081"
    networks:
      pdnsnet:
        ipv4_address: 172.30.0.10
    volumes:
      - primary-data:/var/lib/powerdns
      - ./docker/pdns/primary.conf:/etc/powerdns/pdns.conf:ro
    # Override the api-key via CLI so the conf file stays generic.
    command: ["--api-key=primary-changeme"]
    healthcheck:
      test: ["CMD", "pdns_control", "rping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  # ---- PDNS Secondary 1 ------------------------------------------------
  pdns-secondary-1-init:
    image: alpine:3.20
    restart: "no"
    command:
      - sh
      - -c
      - |
        set -eu
        apk add --no-cache sqlite >/dev/null
        sh /init.sh
        chown -R 953:953 /var/lib/powerdns
        chmod -R u+rwX /var/lib/powerdns
    environment:
      DB: /var/lib/powerdns/pdns.sqlite
      SCHEMA: /schema.sqlite3.sql
      PRIMARY_IPS: "172.30.0.10"
      SELF_NS: "pdns-secondary-1"
    volumes:
      - secondary-1-data:/var/lib/powerdns
      - ./docker/pdns/init-secondary.sh:/init.sh:ro
      - ./docker/pdns/schema.sqlite3.sql:/schema.sqlite3.sql:ro
    networks:
      - pdnsnet

  pdns-secondary-1:
    image: powerdns/pdns-auth-49:latest
    restart: unless-stopped
    depends_on:
      pdns-secondary-1-init:
        condition: service_completed_successfully
    ports:
      - "5301:53"
      - "5301:53/udp"
      - "8082:8081"
    networks:
      pdnsnet:
        ipv4_address: 172.30.0.11
    volumes:
      - secondary-1-data:/var/lib/powerdns
      - ./docker/pdns/secondary.conf:/etc/powerdns/pdns.conf:ro
    command: ["--api-key=secondary-1-changeme"]
    healthcheck:
      test: ["CMD", "pdns_control", "rping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  # ---- PDNS Secondary 2 ------------------------------------------------
  pdns-secondary-2-init:
    image: alpine:3.20
    restart: "no"
    command:
      - sh
      - -c
      - |
        set -eu
        apk add --no-cache sqlite >/dev/null
        sh /init.sh
        chown -R 953:953 /var/lib/powerdns
        chmod -R u+rwX /var/lib/powerdns
    environment:
      DB: /var/lib/powerdns/pdns.sqlite
      SCHEMA: /schema.sqlite3.sql
      PRIMARY_IPS: "172.30.0.10"
      SELF_NS: "pdns-secondary-2"
    volumes:
      - secondary-2-data:/var/lib/powerdns
      - ./docker/pdns/init-secondary.sh:/init.sh:ro
      - ./docker/pdns/schema.sqlite3.sql:/schema.sqlite3.sql:ro
    networks:
      - pdnsnet

  pdns-secondary-2:
    image: powerdns/pdns-auth-49:latest
    restart: unless-stopped
    depends_on:
      pdns-secondary-2-init:
        condition: service_completed_successfully
    ports:
      - "5302:53"
      - "5302:53/udp"
      - "8083:8081"
    networks:
      pdnsnet:
        ipv4_address: 172.30.0.12
    volumes:
      - secondary-2-data:/var/lib/powerdns
      - ./docker/pdns/secondary.conf:/etc/powerdns/pdns.conf:ro
    command: ["--api-key=secondary-2-changeme"]
    healthcheck:
      test: ["CMD", "pdns_control", "rping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  # ---- PDNS Secondary 3 ------------------------------------------------
  pdns-secondary-3-init:
    image: alpine:3.20
    restart: "no"
    command:
      - sh
      - -c
      - |
        set -eu
        apk add --no-cache sqlite >/dev/null
        sh /init.sh
        chown -R 953:953 /var/lib/powerdns
        chmod -R u+rwX /var/lib/powerdns
    environment:
      DB: /var/lib/powerdns/pdns.sqlite
      SCHEMA: /schema.sqlite3.sql
      PRIMARY_IPS: "172.30.0.10"
      SELF_NS: "pdns-secondary-3"
    volumes:
      - secondary-3-data:/var/lib/powerdns
      - ./docker/pdns/init-secondary.sh:/init.sh:ro
      - ./docker/pdns/schema.sqlite3.sql:/schema.sqlite3.sql:ro
    networks:
      - pdnsnet

  pdns-secondary-3:
    image: powerdns/pdns-auth-49:latest
    restart: unless-stopped
    depends_on:
      pdns-secondary-3-init:
        condition: service_completed_successfully
    ports:
      - "5303:53"
      - "5303:53/udp"
      - "8084:8081"
    networks:
      pdnsnet:
        ipv4_address: 172.30.0.13
    volumes:
      - secondary-3-data:/var/lib/powerdns
      - ./docker/pdns/secondary.conf:/etc/powerdns/pdns.conf:ro
    command: ["--api-key=secondary-3-changeme"]
    healthcheck:
      test: ["CMD", "pdns_control", "rping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  # ---- The app ---------------------------------------------------------
  # Boots with PROVISIONING_FILE pointing at the bundled provisioning YAML,
  # which pre-registers all four PDNS backends and a starter zone template.
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: runner
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      pdns-primary:
        condition: service_healthy
      pdns-secondary-1:
        condition: service_healthy
      pdns-secondary-2:
        condition: service_healthy
      pdns-secondary-3:
        condition: service_healthy
    ports:
      - "3000:3000"
    networks:
      - pdnsnet
    volumes:
      - ./provisioning.primary-secondary.example.yaml:/etc/powerdns-authadmin/provisioning.yaml:ro
    environment:
      NODE_ENV: ${NODE_ENV:-production}
      PORT: 3000
      APP_URL: ${APP_URL:-http://localhost:3000}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      DATABASE_URL: postgres://pdns:pdns@postgres:5432/powerdns_authadmin
      REDIS_URL: redis://redis:6379
      APP_SECRET_KEY: ${APP_SECRET_KEY:?must be set; generate with openssl rand -base64 32}
      APP_ENCRYPTION_KEY: ${APP_ENCRYPTION_KEY:?must be set; generate with openssl rand -base64 32}
      BOOTSTRAP_ADMIN_EMAIL: ${BOOTSTRAP_ADMIN_EMAIL:-admin@example.com}
      BOOTSTRAP_ADMIN_PASSWORD: ${BOOTSTRAP_ADMIN_PASSWORD:-bootstrap-admin-pw-changeme}
      LOCAL_AUTH_ENABLED: "true"
      APP_PDNS_ALLOW_PRIVATE_NETWORKS: "true"
      MIGRATE_ON_BOOT: ${MIGRATE_ON_BOOT:-true}
      SEED_ON_BOOT: ${SEED_ON_BOOT:-true}
      PROVISIONING_FILE: /etc/powerdns-authadmin/provisioning.yaml
      PROVISION_ON_BOOT: ${PROVISION_ON_BOOT:-true}
      APP_PDNS_ALLOW_INSECURE_HTTP: ${APP_PDNS_ALLOW_INSECURE_HTTP:-true}
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://localhost:3000/healthz').then(r=>r.ok?process.exit(0):process.exit(1)).catch(()=>process.exit(1))",
        ]
      interval: 15s
      timeout: 5s
      retries: 5
      start_period: 30s

volumes:
  postgres-data:
  redis-data:
  primary-data:
  secondary-1-data:
  secondary-2-data:
  secondary-3-data: