# Docker Networking Explained: Bridge Networks, Ports and DNS

> How Docker networking works: the default bridge, user-defined networks with DNS, publishing ports, host and none drivers, and how to debug connectivity.

- Source: https://www.itwonderlab.com/docker-networking/
- Published: 2026-10-06
- Updated: 2026-10-06
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

## How containers talk to each other

Every container gets its own network stack: its own IP address, routing table and ports. Docker connects containers through **networks**. You rarely need to know IP addresses: containers on the same user-defined network find each other **by name**.

![Docker networking: the browser reaches the web container through a published port, and the web, api and db containers talk to each other by name on a user-defined bridge network, while the database publishes no port](https://www.itwonderlab.com/media/tutorials/Diagrams/ITWL-Docker-Networking.svg "A user-defined bridge network with DNS, and one published port")

## Network drivers

| Driver | What it does |
|---|---|
| `bridge` | The default. A private virtual network on the Docker host. Containers can reach the outside through NAT. |
| `host` | The container shares the network of the host: no isolation, no port mapping. Inside Rancher Desktop the "host" is the Linux VM, not your computer. |
| `none` | No network except loopback. |
| `overlay` | Connects containers across several hosts (Swarm). |
| `macvlan` | Gives the container its own MAC address on your physical network. |

## The default bridge vs a user-defined bridge

Containers started without `--network` join the **default bridge**, where they can reach each other only by IP address. Create your own network and you get automatic DNS, better isolation and the ability to connect and disconnect containers while they run.

```shell
$ docker network create app-net
$ docker run -d --name db  --network app-net -e POSTGRES_PASSWORD=secret postgres:17
$ docker run --rm --network app-net postgres:17 \
    psql -h db -U postgres -c "SELECT 'it works' AS result;"
```

The second container reaches the first one with the hostname `db`: Docker's embedded DNS resolves container names (and, in Compose, service names) on user-defined networks.

## Publishing ports

Containers are not reachable from outside the network by default. `-p` (or `--publish`) maps a port of the host to a port of the container:

```shell
$ docker run -d --name web -p 8080:80 nginx:1.27          # all interfaces
$ docker run -d --name web2 -p 127.0.0.1:8081:80 nginx:1.27   # only your computer
$ docker run -d -P nginx:1.27                              # random host port for each EXPOSE
$ docker port web
80/tcp -> 0.0.0.0:8080
```

> [!TIP]
> Publish a database only if you need to reach it from your computer, and bind it to `127.0.0.1`. Other containers on the same network reach it by name without publishing anything, as in the diagram.

### Ports below 1024 on Linux

Rancher Desktop on Linux cannot publish ports below 1024 (such as 80 or 443) unless you allow it:

```shell
$ sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80
```

Add it to `/etc/sysctl.d/` to make it permanent.

## Connect and inspect

```shell
$ docker network ls
$ docker network inspect app-net            # subnet, gateway and connected containers
$ docker network connect app-net web        # add a running container to a network
$ docker network disconnect app-net web
$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
```

A container can be on several networks. A frequent pattern is a **frontend** network for the proxy and the app and a **backend** network for the app and the database, so the proxy can never reach the database.

```shell
$ docker network create --internal backend   # no access to the outside world at all
```

## Debugging connectivity

Most problems are one of these:

1. **"Connection refused" from the host**: the port is not published (`docker port`) or the application listens only on `127.0.0.1` inside the container. Bind it to `0.0.0.0`.
2. **Name does not resolve**: the containers are not on the same **user-defined** network. The default bridge has no DNS.
3. **Works with the IP but not with the name**: you are on the default bridge.
4. **`localhost` inside a container**: it is the container itself, not your computer. To reach a service on your computer from a container use `host.docker.internal` (available in Docker Desktop and Rancher Desktop) or the IP of the host.

Use a tool container that shares the network of the failing one:

```shell
$ docker run --rm -it --network container:web nicolaka/netshoot
# inside: ping db, nslookup db, curl -v http://api:3000, ss -tlnp
```

## DNS and proxies

Containers inherit the DNS configuration of the daemon. In a corporate network with a proxy, configure it in the engine and not in every Dockerfile. [Rancher Desktop](https://www.itwonderlab.com/rancher-desktop/) can pass the proxy settings of the host to the VM, and the Windows version supports domain names and wildcards in its no-proxy list. See [troubleshooting](https://www.itwonderlab.com/docker-rancher-desktop-troubleshooting/).

## Next steps

Define networks, volumes and services in one file with [Docker Compose](https://www.itwonderlab.com/docker-compose-tutorial/).
