Docker Networking

intermediate
11 min

Docker Networking

A single container is useful; containers talking to each other is where real applications live. An API needs its database, a web app needs its cache. This lesson explains how Docker networking works, how containers find each other by name, and how ports connect containers to the outside world.

The Default Networks

List the networks Docker creates out of the box:

bash
docker network ls

You will see three: bridge, host, and none.

  • bridge - the default. Containers get a private IP on a virtual network inside the host and reach the internet through NAT.
  • host - the container shares the host network stack directly. No isolation, no port mapping needed; Linux only.
  • none - no networking at all, for fully isolated workloads.

Why You Should Create Your Own Network

Containers on the default bridge can reach each other only by IP address, which changes between restarts. Containers on a user-defined bridge network get something much better: automatic DNS. Every container can reach every other container on the same network by container name.

bash
docker network create appnet docker run -d --name db --network appnet -e POSTGRES_PASSWORD=secret postgres:16 docker run -d --name api --network appnet -p 3000:3000 my-api

Inside the api container, the database is reachable simply as db:5432. No IP addresses, no configuration - the connection string is just:

postgres://postgres:secret@db:5432/postgres

This name-based discovery is the foundation Docker Compose builds on, and it is the pattern used in virtually every multi-container setup.

Publishing Ports

Container networks are private. To accept traffic from outside the host, publish a port with -p host:container:

bash
docker run -d -p 8080:80 nginx # host 8080 -> container 80 docker run -d -p 127.0.0.1:5432:5432 postgres:16 # only local connections docker run -d -p 80 nginx # random host port, see docker ps

Two details worth remembering:

  • Binding to 127.0.0.1 keeps a service private to the host machine - do this for databases in development so they are not exposed to your network.
  • Only published ports are reachable from outside; container-to-container traffic on a shared network needs no -p at all.

Inspecting and Debugging Networks

bash
docker network inspect appnet # who is connected, what IPs docker exec api ping db # test name resolution and reachability docker port api # show port mappings

You can also connect and disconnect running containers without restarting them:

bash
docker network connect appnet existing-container docker network disconnect appnet existing-container

A container can sit on several networks at once, which is a simple way to segment traffic - for example, a backend network for api and db, and a frontend network for api and proxy, so the proxy can never reach the database directly.

Reaching the Host from a Container

Occasionally a container needs to call a service running on the host itself. Use the special name host.docker.internal (built into Docker Desktop; on Linux add --add-host=host.docker.internal:host-gateway).

bash
docker run --add-host=host.docker.internal:host-gateway -it --rm alpine ping host.docker.internal

Key Takeaways

  • Docker ships with bridge, host, and none networks; the default bridge is limited.
  • Always create user-defined networks: they give containers DNS names matching container names.
  • -p host:container exposes services externally; bind to 127.0.0.1 to keep them local.
  • Containers on the same network communicate freely without published ports.
  • Multiple networks per container enable simple, effective traffic segmentation.

Next up: Environment Variables and Configuration, where you will learn to configure the same image differently for dev, staging, and production.

Docker Networking - Docker | CodeYourCraft | CodeYourCraft