Isolating Self-Hosted Services with Docker Networks
Give every self-hosted service its own Docker network and limit cross-service talk so one compromised container cannot walk the whole stack.
Netbay Cloud Team
Netbay Engineering
On this page
In a default Docker setup every container can reach every other container by name, and the default bridge lets containers talk to each other freely. For a homelab that is convenient and almost always wrong. If one container is compromised, it becomes a foothold from which every other service is one hostname lookup away. Network isolation fixes this by reversing the default: each service gets its own bridge network, and containers only share a network when they genuinely need to communicate. The proxy is the one node allowed to reach everything, because it is the designated front door.
Build Separate Networks Per Concern
The pattern is one bridge network per logical service group. A typical app might have a web bridge for the reverse proxy plus the dashboard, and a private bridge for the app plus its database, with the app joining both so it can serve the proxy and reach its DB while the DB stays invisible to everything else.
docker network create proxy-net
docker network create web-bridge
docker network create db-net
docker network create cache-netNaming networks explicitly and reusing them across compose files keeps your topology visible in a single docker network ls. The virtual segregations you draw here are the same idea network engineers apply with physical VLANs — separate broadcast and reachability domains per tenant — but at container granularity and without the cabling.
Wiring Compose to Multiple Networks
In Docker Compose you attach a service to several networks, exposing only the interfaces it needs. Here the web app joins both the web-bridge (to talk to the proxy) and the db-net (to reach Postgres), while the database only ever sees db-net.
services:
app:
networks:
- web-bridge
- db-net
db:
image: postgres:16
networks:
- db-net
volumes:
- pgdata:/var/lib/postgresql/data
networks:
web-bridge:
external: true
db-net:
external: true
volumes:
pgdata:Because Postgres is not on web-bridge, the reverse proxy cannot reach it directly, and no other web service can either. The only path into the database is through the application container that declares membership in db-net.
Beyond Containers: The VLAN Layer
Container networks handle east-west traffic between processes on one host. If you later run multiple hosts or want physical separation, a VLAN splits the switch itself into distinct broadcast domains — management traffic, public services, and storage on different VLANs, with firewall rules between them. The mental model is the same as the Docker bridge: reachability is the thing you grant, not the thing you assume.
# networkd-style example for a tagged interface on Linux
[Match]
Name=eth0
[Network]
VLAN=vm-public
VLAN=vm-mgmt
[Link]
RequiredForOnline=noThat snippet only sketches the tagging step; the discipline is to draw the boundaries on paper first — which service may talk to which — then implement each boundary with either a Docker network or a VLAN and re-check the map after every change.
Verify What You Drew
A boundary written into compose is only useful if it is actually true, so prove it at least once per stack. Fire up a throwaway container on the web-bridge and try to reach the database container by name. It should fail to resolve or connect. Then hop into a container that is on db-net and confirm the reverse is possible. This thirty-second check catches the classic mistake of a service attached to more networks than you intended — which quietly flattens your isolation back into one big flat network.
# from a throwaway container on the public bridge:
docker run --rm --network web-bridge alpine wget -q -O- http://db:5432
# expected: fails to reach the databaseIf that command succeeds, the database is reachable from the wrong network and your separation has a hole. Track down the extra network attachment and remove it before moving on. Isolation you never tested is a guess you can only verify the day a compromise happens — far too late to enjoy the finding.
Keep a Network Map
As the stack grows, the mental map fades and the risk of "just add this one container to proxy-net" creeps up. Keep a short list — in git, next to your compose file — naming each network and the services allowed on it. Reviewing it whenever you add a service turns the gone-later decision into a deliberate one and keeps the whole topology auditable.
Takeaway
Isolation is a habit you apply as you add services, not a cleanup you do later. Give each group its own bridge, let only the proxy cross, and treat the database like it lives on another planet. The same reachability-first thinking scales up to VLANs when your lab grows bigger than one box. A single Netbay Lucknow VPS can host an isolated multi-network stack comfortably, and you can redeploy the whole topology fresh from netbayhosts.in in under a minute if you ever want to rebuild it.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance