Architecture at a glance
The lab is one writable domain controller plus a set of optional sibling services that behave like separate machines on the LAN. The tricky part is networking: a domain controller cannot be cleanly contained, and the sibling services need real LAN identities, so two different Docker network modes are in play at once.
The pieces
Section titled “The pieces”flowchart TB
client["LAN clients"]
subgraph LAN["LAN · 10.22.22.0/24"]
ndc1["dc1 · 10.22.22.22<br/><b>host networking</b>"]
nprint1["print1 · 10.22.22.23<br/>macvlan · member + CUPS"]
nrodc1["rodc1 · 10.22.22.24<br/>macvlan · read-only replica"]
nprintsnmp["print-snmp · 10.22.22.25<br/>macvlan · SNMP device"]
nprintipp["print-ipp · 10.22.22.26<br/>macvlan · IPP device"]
end
client --> nprint1
client --> ndc1
nprint1 -. "/32 detour" .-> ndc1
nrodc1 -. "/32 detour" .-> ndc1
nprintsnmp -. "/32 detour" .-> ndc1
nprintipp -. "/32 detour" .-> ndc1
Generated from .env by make diagrams. Solid arrows are the LAN paths clients
use; dotted arrows are the /32 bridge detour each macvlan child needs to reach
the DC (its own macvlan parent).
dc1runs onnetwork_mode: host. A domain controller serves DNS (53), Kerberos (88), LDAP (389/636), SMB (445), kpasswd (464), the Global Catalog (3268/3269), and a dynamic RPC range from 49152. You cannot publish that last range with-p, so the DC owns those ports on the host’s LAN IP, exactly as a real DC would. See Why host networking.print1,rodc1,print-snmp,print-ippeach get their own LAN IP via macvlan, so a real Windows client mounts\\print1on native port 445 with no NAT. But a macvlan child cannot address its own parent host (which isdc1), so these services also attach the sharedsambabridge and pin a/32route to the DC over it. See The macvlan + bridge detour.
How sibling app containers reach the DC
Section titled “How sibling app containers reach the DC”An app you are testing (a fax broker, an IdP, a directory-aware service) joins
the shared external samba bridge network and reaches the DC through the
host gateway:
services: my-app: networks: [samba] extra_hosts: - "host.docker.internal:host-gateway" dns: - 172.17.0.1 # host gateway = the DC's internal DNS # LDAP URL: ldap://host.docker.internal # Realm: value of SAMBA_REALMnetworks: samba: external: trueFor TLS (LDAPS on 636) you must connect by the certificate name, not through the gateway. The details and the reason are on the host networking page.
IP and port map
Section titled “IP and port map”The defaults below come from .env. The full table of variables is in the
.env reference, and the addressing rationale is in
the network map.
| Host | Default IP | Network mode | Serves |
|---|---|---|---|
dc1 | 10.22.22.22 | host | DNS, Kerberos, LDAP/LDAPS, SMB, GC |
print1 | 10.22.22.23 | macvlan + bridge | SMB print (445), CUPS/IPP (631) |
rodc1 | 10.22.22.24 | macvlan + bridge | read-only DNS + LDAP |
print-snmp | 10.22.22.25 | macvlan + bridge | SNMP (161) printer device MIBs |
print-ipp | 10.22.22.26 | macvlan + bridge | IPP Everywhere (8631-8633) |
Beyond the DC — the clinical ecosystem
Section titled “Beyond the DC — the clinical ecosystem”The macvlan siblings above live in this repo’s compose. The lab also has three
larger sibling stacks, each its own repository, that turn the DC into a working
hospital: OpenEMR (the electronic record), Simulated Hospital (a live
HL7v2 feed), and the OpenIntegrationEngine (the interface engine that routes
the feed into the record). Together with the DC they form four planes — identity,
application, activity, integration — connected by a dedicated hl7-bus network.
See The four-plane architecture for how they fit and Run the clinical ecosystem for the runbook. Simulated Hospital has its own deep dive.
State and disposability
Section titled “State and disposability”All durable state lives in named volumes (samba-data holds the AD database,
samba-conf the config, plus logs and home directories). Provisioning keys off
sam.ldb, so make down followed by make up brings the same domain back.
make nuke deletes the volumes to start fresh. That disposability is what makes
the lab safe to experiment in.