# ScadaBridge Env2 Docker Infrastructure A second Docker deployment of a minimal ScadaBridge cluster topology, designed to run **concurrently with** the primary `docker/` stack so the Transport (#24) feature can be exercised end-to-end across two real environments. See [`docs/plans/2026-05-24-second-environment-design.md`](../docs/plans/2026-05-24-second-environment-design.md) for the design rationale. ## Cluster Topology ``` ┌───────────────────┐ │ Traefik LB :9100 │ ◄── CLI / Browser │ Dashboard :8181 │ └────────┬──────────┘ │ routes to active node ┌──────────────────────┼──────────────────────────────┐ │ Env2 Central Cluster │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ env2-central-a │◄──►│ env2-central-b │ │ │ │ Web UI :9101 │ │ Web UI :9102 │ │ │ │ Akka :9111 │ │ Akka :9112 │ │ │ └────────┬─────────┘ └─────────────────┘ │ │ │ │ └───────────┼─────────────────────────────────────────┘ │ Akka.NET Remoting ▼ ┌────────────────────┐ │ Env2 Site-X │ │ (Env2 Site X) │ │ │ │ node-a ◄──► node-b│ │ Akka :9121 :9122 │ │ gRPC :9123 :9124 │ └────────────────────┘ ``` ## Port Allocation Env2 host ports are the primary's ports + 100. Both stacks can run simultaneously. | Node | Container Name | Host Web | Host Akka | Host gRPC | Internal | |------|----------------|----------|-----------|-----------|----------| | Traefik LB | `scadabridge-env2-traefik` | 9100 | — | — | 80 (proxy), 8080 (dashboard host:8181) | | Central A | `scadabridge-env2-central-a` | 9101 | 9111 | — | 5000 (web), 8081 (Akka) | | Central B | `scadabridge-env2-central-b` | 9102 | 9112 | — | 5000 (web), 8081 (Akka) | | Site-X A | `scadabridge-env2-site-x-a` | — | 9121 | 9123 | 8082 (Akka), 8083 (gRPC) | | Site-X B | `scadabridge-env2-site-x-b` | — | 9122 | 9124 | 8082 (Akka), 8083 (gRPC) | ## Shared Infrastructure Env2 attaches to the existing `scadabridge-net` Docker bridge network and reuses these primary infra containers: | Service | Container | What env2 uses it for | |---------|-----------|-----------------------| | MS SQL | `scadabridge-mssql` | Env2-specific databases `ScadaBridgeConfig2` / `ScadaBridgeMachineData2` | | LDAP | `scadabridge-ldap` | Authentication (same test users) | | SMTP | `scadabridge-smtp` | Notification capture in Mailpit (env2 emails distinguishable by `FromAddress`) | | OPC UA | `scadabridge-opcua` | Simulated tags for site-x data connections | | REST API | `scadabridge-restapi` | External REST API testing | ## Commands ### First-Time Setup ```bash # 1. Make sure primary infra is up (creates scadabridge-net, scadabridge-mssql, etc.) cd infra && docker compose up -d && cd .. # 2. Build image + create env2 databases + deploy env2 containers bash docker-env2/deploy.sh # 3. Seed env2's single test site (first-time only) bash docker-env2/seed-sites.sh ``` The seed also creates a **native alarm source demo**: a `MxAlarmDemo` template with a `GalaxyAlarms` native alarm source bound to the shared MxGateway connection, plus a deployed `MxAlarmDemo-1` instance on site-x. This exercises the read-only native alarm mirror end-to-end — mirrored alarms appear live in the Central UI Debug View with severity and condition badges. Verify the binding with: ```bash scadabridge --url http://localhost:9100 template native-alarm-source list --template-id ``` ### After Code Changes ```bash bash docker-env2/deploy.sh ``` The Docker build is shared with the primary stack — if you've just run `docker/deploy.sh`, the env2 build hits a fully cached image. ### Running Both Stacks Concurrently ```bash bash docker/deploy.sh # primary bash docker-env2/deploy.sh # env2 ``` Both UIs are now reachable: - Primary: http://localhost:9000 - Env2: http://localhost:9100 ### Teardown ```bash bash docker-env2/teardown.sh ``` Containers stop, volumes (data + logs) preserved. To also drop the env2 databases: ```bash docker exec scadabridge-mssql /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'ScadaBridge_Dev1#' -C \ -Q "DROP DATABASE ScadaBridgeConfig2; DROP DATABASE ScadaBridgeMachineData2;" ``` ### CLI Access ```bash dotnet run --project src/ZB.MOM.WW.ScadaBridge.CLI -- \ --url http://localhost:9100 \ --username multi-role --password password \ template list ``` ### View Logs ```bash docker compose -f docker-env2/docker-compose.yml logs -f docker logs -f scadabridge-env2-central-a ``` ## Test Users Same as primary (env2 shares LDAP). See `infra/glauth/config.toml` and primary `docker/README.md`. ## Transport Testing Workflow See [`docs/plans/2026-05-24-second-environment-verification.md`](../docs/plans/2026-05-24-second-environment-verification.md) for the manual golden-path checklist. ## What's Different from Primary - Single site (`site-x`) instead of three (`site-a/b/c`). - Host port range 91XX vs primary 90XX. - Container names prefixed `scadabridge-env2-`. - Databases `ScadaBridgeConfig2` / `ScadaBridgeMachineData2` on the **shared** `scadabridge-mssql`. - `Transport.SourceEnvironment` = `"docker-cluster-env2"` (stamped into exported bundle manifests). - Distinct `Security.JwtSigningKey` (sessions cannot cross envs).