Skip to content

Docker networks, names, ports and namespaces

Extracted from the master document on 2026-09-04. §N numbering preserved so cross-references don’t break.

Name: proxy ← the network's name
Driver: bridge ← the network type
Subnet: 172.22.0.0/16
Gateway: 172.22.0.1

It was created once, outside of any stack:

Terminal window
docker network create proxy

Every stack that has to receive traffic from Caddy declares:

services:
app:
networks:
- proxy
networks:
proxy:
external: true

external: true means: the network already exists outside this stack; Compose must reuse it and not create a new private network with that name. Without that line, each stack would end up on its own network and Caddy would not see anyone.

Driver What it is When it applies here
bridge virtual network local to one Docker host the one we use (proxy)
host shares the host’s networking not used
none no network not used
overlay multi-host network (Swarm) out of scope
macvlan the container appears as a machine on the LAN not used
ipvlan L2/L3 variant on the physical network not used
Caddy ───── the `proxy` network ───── Vaultwarden ✅ they see each other by name
Caddy ──X── (no shared network) ──X── Service ❌ you have to publish a port
and reach it through a
routable host IP
ports:
- "8080:80" # HOST:8080 ──► CONTAINER:80 (opens on the whole LAN)
- "127.0.0.1:8080:80" # host loopback only
EXPOSE (Dockerfile) / expose (Compose)
→ DOCUMENTS that the service uses that port. It opens nothing.
ports
→ CREATES a real way in from the host to the container.

Design consequence: if Caddy and the backend share the proxy network, the backend does not need ports. Publishing a port that only Caddy is going to use means exposing attack surface on the LAN in exchange for nothing.

The initial Caddyfile said reverse_proxy 127.0.0.1:8000 and it failed.

WHAT WAS EXPECTED WHAT ACTUALLY HAPPENS
───────────────────── ──────────────────────────
Caddy Caddy container
└─► 127.0.0.1:8000 └─► 127.0.0.1:8000
└─► docker-host └─► looks INSIDE
└─► Vaultwarden ✅ Caddy itself ❌
127.0.0.1 inside Caddy = Caddy
127.0.0.1 inside Vaultwarden = Vaultwarden
127.0.0.1 on docker-host = docker-host

Every container has its own network namespace. localhost inside a container refers to that container, never to the host or to another container.

The fix was the proxy network + reverse_proxy vaultwarden:80.