lox & hub · lockhub
Networks and address pools
lox run gives a workspace several Docker networks: the hub's own
(lockhub, internal), the hub's route out when a chat facade or mobile push
needs one (egress-hub), the mobile listener's (mobile-hub), and per lock:
| lock | networks |
|---|---|
| with an allowlist (a database, a broker, a remote file store, …) | locknet-<name> (internal), gwlink-<name> (internal, between its gateway's two halves), out-<name> (the gateway's route out) |
| with no endpoint (lockfile local, locklog with local sources) | locknet-<name> (internal), or the hub's alone |
| lockhttp | egress-<name> (its own policy's route out) |
lox-run.md says why each one exists.
Each network's own small subnet #
Left to itself, Docker takes every new network's subnet from its default
address pools, a whole /16 or /20 each. A stock daemon has 31 of them
(172.17.0.0/16 to 172.31.0.0/16, then 192.168.0.0/16 in /20s). A
workspace of six locks used 15 before lockhub#175; a second workspace, lea
and a few compose projects later, Docker refused every new network:
Error response from daemon: all predefined address pools have been fully subnetted
So lox run sets each network's subnet in the compose file (ipam.config)
from a range of its own, the workspace's pool: a /24 for lockhub (the
hub, every lock and lea's gates) and a /28 for every other network (two or
three containers each). The default pool is 10.123.0.0/16: room for about
100 workspaces of ten locks, and none of Docker's default address pools is
touched.
Before each run, lox run reads the subnets of every network the engine has
(docker network inspect): a network of the workspace keeps its subnet while
it is still free and of the right size, so nothing is recreated; a new one
takes the pool's first free block. Two workspaces never overlap: each one's
networks are taken subnets for the other. A workspace made before lox set
subnets moves its networks into the pool on its first lox run (compose
recreates them, and the containers on them).
If the pool collides with a network of yours (a VPN or a LAN on
10.123.0.0/16: the locks could not reach its hosts), pick another private
range in lockfamily.yaml:
network:
pool: 10.200.0.0/16 # private IPv4, /8 to /24
The review shows network pool 10.200.0.0/16; the next lox run moves the
networks.
When the engine refuses a network #
Another program may take a subnet between lox run's read and compose's
create, or a pool may be full. lox run then stops with:
the engine refused a network of this workspace for its addresses (...): nothing new was started; lox run again picks free subnets, ...
It removes the networks of the workspace that compose made before it stopped
and no container uses, and applies nothing: the next lox run reviews the
same change again. A pool with no free block left says so before anything
starts (no free subnet left in the network pool): remove unused networks
(docker network prune) or set a larger network.pool.
lox doctor #
lox doctor checks both ranges:
ok networks: pool 10.123.0.0/16 holds a subnet for each network the workspace may need (27)
warn networks: the engine's default address pools have 2 of 31 subnets free: lea and other compose projects soon fail with ...
The first line warns when the next lox run could not place its networks.
The second counts the free subnets of the engine's default address pools
(the ones default-address-pools in /etc/docker/daemon.json sets, or
Docker's own), which lea (lea-internal-<id>, lea-egress) and your other
compose projects still take theirs from; it warns below 4. Podman has pools
of its own: the second line is left out.
default-address-pools #
To give Docker room for many more networks, split a large private range into
small subnets, in /etc/docker/daemon.json:
{
"default-address-pools": [
{"base": "10.200.0.0/16", "size": 24}
]
}
That is 256 networks of 254 addresses. Pick a range that no network of yours
and no network.pool uses, then restart Docker (sudo systemctl restart docker): it stops every container, and the networks that exist keep their
subnets; only new ones take the new pools. Docker Desktop: Settings, Docker
Engine, the same JSON.