Docker and Kubernetes course menu
Docker Networking Explained: Connect Containers Together
How Docker networks work: the default bridge, user-defined networks, DNS by container name, publishing ports, and why localhost inside a container is not your computer.
On this page
Each container has its own network stack and IP address. Docker networks let containers talk to each other.
Default networks#
docker network ls --format 'table {{.Name}}\t{{.Driver}}'NAME DRIVER
bridge bridge
host host
none nulllocalhost in a container#
This confuses nearly everyone. Inside a container, localhost means that container, not your computer, and not other containers.
docker run -d --name web nginx:1.30-alpine > /dev/null
sleep 2
docker run --rm alpine:3.24 sh -c 'wget -qO- -T 2 http://localhost 2>&1 | head -n 1'
docker rm -f web > /dev/nullwget: can't connect to remote host: Connection refusedThe second container has nothing on its own port 80.
User-defined networks#
Create a network, and put containers on it. Containers can then reach each other by name, because Docker runs a small DNS server:
docker network create app-net > /dev/null
docker run -d --name web --network app-net nginx:1.30-alpine > /dev/null
sleep 2
docker run --rm --network app-net alpine:3.24 wget -qO- http://web | grep -o '<title>.*</title>'<title>Welcome to nginx!</title>The name web worked, and no port was published to the host. This is how an app talks to its database:
postgres://user:pass@db:5432/app
^^ the container's nameThe default bridge network does not provide this name lookup, so always create your own. Docker Compose does it for you.
Networks isolate#
A container on another network cannot reach web:
docker run --rm alpine:3.24 sh -c 'wget -qO- -T 2 http://web 2>&1 | head -n 1'wget: bad address 'web'Use this for security. For example, a database can be on a private network that only the app can reach.
Published ports#
-p is for traffic from outside Docker. Containers on the same network use the container's own port, and need no -p.
Browser --> localhost:8080 --> web:80 (needs -p 8080:80)
app container --> db:5432 (no -p needed)Inspect a network#
docker network inspect app-net --format '{{range .Containers}}{{.Name}} {{end}}'
docker exec web sh -c 'cat /etc/resolv.conf | grep nameserver'web
nameserver 127.0.0.11Connect a running container#
A container can join several networks:
docker run -d --name tool alpine:3.24 sleep 30 > /dev/null
docker network connect app-net tool
docker exec tool wget -qO- http://web | grep -c nginx
docker rm -f tool web > /dev/null
docker network rm app-net7
app-netReaching the host#
From a container, Docker Desktop provides the name host.docker.internal, which means your computer. On Linux, add it yourself:
docker run --add-host=host.docker.internal:host-gateway alpine:3.24 ping host.docker.internalCommon mistakes#
Practice#
Practice exercise
Create a network lab, start nginx:1.30-alpine on it with the name api, and from an Alpine container fetch http://api, printing only the first line of the page. Then clean up.
Show solution
docker network create lab > /dev/null
docker run -d --name api --network lab nginx:1.30-alpine > /dev/null
sleep 2
docker run --rm --network lab alpine:3.24 wget -qO- http://api | head -n 1
docker rm -f api > /dev/null
docker network rm lab > /dev/null<!DOCTYPE html>Key takeaway#
Finished this lesson?
Related lessons
Recommended Docker and Kubernetes resources
- Docker Deep Dive by Nigel Poulton
A practical guide to how Docker works, for readers who have finished the basics.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.