Docker Networking Basics
This page is a hands-on intro to Docker's built-in network drivers - bridge, host, and none - and to publishing ports so the outside world can reach a container.
Everything here is single-host Docker Engine; Kubernetes networking is a separate model covered elsewhere.
Prerequisites
- Docker Engine 29.6.1 with BuildKit (the default backend).
- Compose v2 (
docker compose, not the legacydocker-compose). - A Linux host or Docker Desktop; commands assume you can run
dockerwithout extra privileges.
docker version --format '{{.Server.Version}}'
docker network lsBasic Examples
1. Inspect the default networks
Every install ships with three networks you cannot delete.
docker network lsbridgeis the default network containers join when you pass no--network.hostshares the host's network namespace directly.nonegives a container no network at all.- These three map to the three built-in drivers of the same name.
2. Run a container on the default bridge
A plain docker run attaches to the default bridge.
docker run -d --name web nginx:1.27
docker inspect -f '{{.NetworkSettings.IPAddress}}' web- The container receives a private IP on the
docker0subnet. - Outbound traffic is NATed to the host address automatically.
- Nothing outside the host can reach that private IP yet.
- The default bridge does not provide DNS resolution between containers.
3. Publish a port to reach the container
Publishing maps a host port to a container port with a DNAT rule.
docker run -d -p 8080:80 --name web nginx:1.27
curl -s http://localhost:8080 | head -n1-p 8080:80forwards host8080to container80.EXPOSEin a Dockerfile is only documentation; it does not publish anything.- Bind to a specific interface with
-p 127.0.0.1:8080:80to avoid exposing publicly. - Use
-Pto publish all exposed ports to random high host ports.
4. Use host networking
The host driver skips the network namespace entirely.
docker run -d --network host --name metrics prom/node-exporter:v1.8.2- The container binds directly to host ports, so no
-pis needed or allowed. - There is no network isolation, which is a security trade-off.
- Port conflicts with the host or other host-net containers are possible.
hostis Linux-native; on Docker Desktop it behaves differently.
5. Disable networking with none
The none driver creates an isolated stack with only loopback.
docker run --rm --network none alpine:3.20 ip addr- Useful for batch jobs that must not touch the network.
- Only the
lointerface exists inside the container. - A strong default for untrusted or purely CPU-bound workloads.
- You can attach a network later with
docker network connect.
6. List and inspect a network
docker network inspect shows the subnet, gateway, and connected containers.
docker network inspect bridge- The
Containersmap lists every attached container and its IP. IPAMshows the subnet and gateway the driver allocated.- Use this first when debugging "which network is this on".
--formatlets you pull a single field for scripts.
7. Map published ports on a running container
Check what a container actually published with docker port.
docker port web- Confirms the host-to-container port mapping in effect.
- Handy when you used
-Pand got random host ports. - Mismatches here explain most "connection refused" reports.
- Pair it with
ss -tlnpon the host to see the listener.
Intermediate Examples
8. Create a user-defined bridge for DNS
Custom bridges add automatic name resolution the default bridge lacks.
docker network create appnet
docker run -d --network appnet --name api myapi:1.0
docker run --rm --network appnet alpine:3.20 ping -c1 api- Containers on a user-defined bridge resolve each other by container name.
- This is the recommended default for multi-container apps.
- Isolation is stronger: only containers on
appnetcan reachapi. - The embedded DNS server lives at
127.0.0.11inside the container.
9. Attach a container to multiple networks
A container can join several networks for segmentation.
docker network create frontend
docker network create backend
docker run -d --name app --network frontend myapp:1.0
docker network connect backend appappcan now reach services on bothfrontendandbackend.- This models a DMZ pattern: public tier plus private tier.
- Each network gets its own interface inside the container.
- Disconnect cleanly with
docker network disconnect backend app.
10. Control published ports in Compose
Compose declares ports and networks in one file.
services:
web:
image: nginx:1.27
ports:
- "127.0.0.1:8080:80"
networks:
- appnet
networks:
appnet:- Compose creates
appnetautomatically and joinswebto it. - The
127.0.0.1:prefix keeps the port off public interfaces. - Services in the same Compose project resolve each other by service name.
- Run it with
docker compose up -d.
11. Debug connectivity from inside a container
When a connection fails, test from the container's own namespace, not the host.
docker run --rm --network appnet nicolaka/netshoot \
sh -c 'nslookup api; nc -zv api 80'netshootbundlesdig,nc,curl, andtcpdumpfor network debugging.- Running it on the same network reproduces the failing container's exact view.
nslookupconfirms whether embedded DNS resolves the target name.nc -zvproves whether the port is actually open and reachable.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).