Skip to content
Laviyx Learn

Try

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.

Intermediate5 min readUpdated
On this page

Each container has its own network stack and IP address. Docker networks let containers talk to each other.

Default networks#

Terminal
docker network ls --format 'table {{.Name}}\t{{.Driver}}'
Output
NAME      DRIVER
bridge    bridge
host      host
none      null
DriverMeaning
bridgeA private network on one host; the default
hostShares the host's network (Linux only)
noneNo network

localhost in a container#

This confuses nearly everyone. Inside a container, localhost means that container, not your computer, and not other containers.

Terminal
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/null
Output
wget: can't connect to remote host: Connection refused

The 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:

Terminal
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>'
Output
<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:

Text
postgres://user:pass@db:5432/app
                     ^^ the container's name

The 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:

Terminal
docker run --rm alpine:3.24 sh -c 'wget -qO- -T 2 http://web 2>&1 | head -n 1'
Output
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.

Text
Browser --> localhost:8080 --> web:80      (needs -p 8080:80)
app container --> db:5432                  (no -p needed)

Inspect a network#

Terminal
docker network inspect app-net --format '{{range .Containers}}{{.Name}} {{end}}'
docker exec web sh -c 'cat /etc/resolv.conf | grep nameserver'
Output
web 
nameserver 127.0.0.11

Connect a running container#

A container can join several networks:

Terminal
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-net
Output
7
app-net

Reaching the host#

From a container, Docker Desktop provides the name host.docker.internal, which means your computer. On Linux, add it yourself:

Terminal
docker run --add-host=host.docker.internal:host-gateway alpine:3.24 ping host.docker.internal

Common 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
Terminal
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
Output
<!DOCTYPE html>

Key takeaway#

Next: Environment Variables and Secrets.

Finished this lesson?

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.