Cloud AI Campus
  • Career paths
  • Learning paths
  • Hands-on Labs
Log in Sign up

๐Ÿงช Hands-on lab · 30 min

Docker โ€” Networking

  1. 1. The default bridge
  2. 2. Custom networks and DNS
  3. 3. Connecting + disconnecting
  4. 4. Port mapping in depth

The default bridge

Every Docker host has a few built-in networks. List them:

docker network ls

You'll see at least:

| Network | Driver | What is it? | |----------|--------|-------------| | bridge | bridge | The default. Every docker run without --network joins this. Containers can reach the outside via NAT; they can NOT resolve each other by name. | | host | host | Container shares the host's network namespace. No isolation, no port mapping needed. | | none | null | No networking at all. |

Inspect the default bridge to see what's connected:

docker network inspect bridge

The Containers array lists every container currently on the network, with its bridge-local IP (usually 172.17.0.x).

Start two containers on the default bridge and try to talk between them by name โ€” it'll fail:

docker run -d --name alpha alpine sleep 600
docker run -d --name beta  alpine sleep 600
docker exec alpha sh -c 'ping -c 1 beta || echo "by name: NO"'
beta_ip=$(docker inspect -f '{{.NetworkSettings.IPAddress}}' beta)
docker exec alpha ping -c 1 "$beta_ip" 2>&1 | tail -3

By IP it works. By name it doesn't. That's a deliberate limitation of the default bridge โ€” and the main reason you should always create your own. Click Verify step when alpha and beta are both running.

Hint

`docker network ls`, `docker network inspect bridge`.

Custom networks and DNS

User-defined bridge networks fix the biggest annoyance with the default: built-in DNS for container names.

Create one:

docker network create --driver bridge app-net
docker network ls

Start two containers, both attached to app-net:

docker run -d --name api  --network app-net alpine sleep 600
docker run -d --name db   --network app-net alpine sleep 600

Now talk between them BY NAME โ€” no IP lookup needed:

docker exec api ping -c 2 db
docker exec api nslookup db

This is what makes microservice topologies practical. Your app container references the database container as db:5432 and the runtime resolves it. No service-discovery sidecar required.

Inspect the network to see members:

docker network inspect app-net | jq '.[0].Containers'

Click Verify step once api can ping db by name.

Hint

Containers on the same user-defined bridge resolve each other by name.

Connecting + disconnecting

A container can be on multiple networks simultaneously. Connect a running container without restarting it:

docker network connect bridge api
docker inspect api --format '{{json .NetworkSettings.Networks}}' | jq

api is now reachable on both networks โ€” the custom app-net (where it can resolve db by name) AND the default bridge. This is how you'd join a "frontend" container to both an isolated backend network and a public-facing one.

Disconnect:

docker network disconnect bridge api
docker inspect api --format '{{json .NetworkSettings.Networks}}' | jq

Patterns this enables:

  • Tiered networks โ€” frontend-net, backend-net, db-net. Web servers join frontend + backend; app servers join backend + db.
  • Migrations โ€” connect to the new network, verify, disconnect from the old one. Zero restart.
  • Sidecars โ€” observability containers on a monitoring-net that's also wired into every other app network.

Click Verify step once api is back on app-net only.

Hint

`docker network connect <net> <container>` joins a running container to another network.

Port mapping in depth

-p is the bridge between the container's port and the host. Five shapes worth knowing:

-p 8080:80                  # host 8080 โ†’ container 80, all interfaces
-p 127.0.0.1:8080:80        # host 8080 โ†’ container 80, ONLY loopback
-p 80                       # random host port โ†’ container 80 (look it up with docker port)
-p 8000-8005:8000-8005      # range
-p 8080:80/udp              # UDP

Try each:

docker run -d --name pub --network app-net -p 8200:80 nginx:alpine
docker run -d --name priv --network app-net -p 127.0.0.1:8201:80 nginx:alpine

# Both reachable on the host:
curl -sI http://localhost:8200/ | head -1
curl -sI http://localhost:8201/ | head -1

# But only one is reachable on the (sandbox's) external interface:
docker port pub
docker port priv

The pub container is published on all host interfaces; priv only on 127.0.0.1. In a real-world deploy, ports you only want behind a reverse proxy on the same host should bind to loopback โ€” never expose them publicly by accident.

To enumerate every published port on the host:

docker ps --format 'table {{.Names}}\t{{.Ports}}'

Click Verify step when both pub and priv are responding.

Hint

`-p 8080:80` host:container, `-p 127.0.0.1:8080:80` to bind only loopback.

© 2026 Cloud AI Campus