Skip to content
6 min read·Lesson 7 of 10

Container Networking

Understand Docker networks, port publishing, container-to-container communication, and the difference between bridge, host, and overlay networks.

Networking is where containers feel different from regular processes — and where most beginner confusion happens. This lesson clears it up.

Network Drivers

DriverWhat it doesWhen to use
bridgeDefault. Containers get a private subnet on the host and reach the outside via NAT.Single-host workloads, local development.
hostContainer shares the host's network namespace. No isolation, no port mapping.Maximum performance, Linux only, when port collisions are not an issue.
noneNo network at all.Batch jobs that should never call out.
overlayMulti-host networking using VXLAN.Docker Swarm; rare outside it. Kubernetes uses CNI plugins instead.
macvlanContainer gets its own MAC address on the physical network.Legacy apps that need to look like a real host.

The Default Bridge

Out of the box, every container attaches to a bridge called bridge. Each container gets a private IP (e.g., 172.17.0.x). This works, but the default bridge has a quirk: containers on it can only reach each other by IP, not by name. So everyone uses user-defined bridge networks instead, which provide automatic DNS-based service discovery.

docker network create app-net

docker run -d --name db --network app-net postgres:16
docker run -d --name api --network app-net \
  -e DATABASE_URL=postgres://postgres@db:5432/postgres \
  myapi:1.0

The API resolves the hostname db to the database container's IP automatically. No /etc/hosts editing, no environment variables full of IP addresses.

Publishing Ports

A container's listening ports are private to its network. To accept traffic from the host or the outside world, you publish a port:

docker run -p 8080:80 nginx                  # host:8080 → container:80
docker run -p 127.0.0.1:8080:80 nginx        # localhost only
docker run -p 8080:80/tcp -p 8080:80/udp ... # both protocols
docker run -P nginx                          # publish all EXPOSEd ports to random hosts

Inspect what's published:

docker port web
# 80/tcp → 0.0.0.0:8080
# 80/tcp → :::8080

Container-to-Container Communication

The general rule: containers on the same user-defined network reach each other by container name; from outside, you reach a container only via published ports.

                Internet
                   │
                   ▼  (port 8080 published)
            ┌────────────┐
            │   Host     │
            │  ┌──────┐  │
            │  │ web  │◀─┼── api network ──▶┌──────┐
            │  │ :80  │  │                  │ api  │
            │  └──────┘  │                  │:3000 │
            │            │                  └──┬───┘
            │            │     api network    │
            │            │                    ▼
            │            │                 ┌──────┐
            │            │                 │  db  │
            │            │                 │:5432 │
            │            │                 └──────┘
            └────────────┘

Reaching the Host From Inside a Container

Sometimes a containerised app needs to reach a service running on the host itself (e.g., a database installed natively while you containerise the app). Use host.docker.internal on Mac/Windows; on Linux you can add a host alias:

docker run --add-host=host.docker.internal:host-gateway myapp

Inspecting Networks

docker network ls                        # list networks
docker network inspect app-net           # see attached containers + IPs
docker network connect app-net some-ctr  # attach an existing container
docker network disconnect app-net some-ctr
docker network rm app-net                # remove (must have no containers attached)

Common Pitfalls

  • "Connection refused" between containers — usually means they are on different networks. Put them on the same user-defined network.
  • Using localhost from inside a container to reach another containerlocalhost is the container itself. Use the other container's name.
  • Port conflict on the host — only one process can listen on a host port. Pick another with -p 8081:80.
  • App binds to 127.0.0.1 inside the container — then no external traffic can reach it. Bind to 0.0.0.0.

From Docker to Kubernetes

In Kubernetes, every pod gets its own network namespace and IP — containers within a pod share the namespace and reach each other via localhost. Pods on different hosts communicate via a CNI (Container Network Interface) plugin like Calico, Cilium, or AWS VPC CNI. The fundamentals you've just learned (DNS, ports, isolation) apply directly.

Key Takeaways

  • Docker creates a default bridge network; containers on the same user-defined network can reach each other by name.
  • Port publishing (-p) opens a port from the host to the container; without it, ports are private.
  • Bridge is the default; host bypasses Docker networking; none disables networking; overlay spans multiple hosts.
  • Use user-defined bridge networks (not the default bridge) for service discovery via DNS.
  • Kubernetes networking is conceptually similar but adds pod-level network namespaces and CNI plugins.

Test your knowledge

Try exam-style practice questions to reinforce what you've learned.

Practice Questions →