Intro
Docker networking is a frequent source of frustration in containerized environments. A container that cannot reach its database, a service that cannot resolve another service by name, or a port mapping that refuses to work can halt development and disrupt production. This article focuses on common Docker networking errors and provides practical fixes with concrete examples. It is written for developers, DevOps consultants, and technical startup teams who need to move from an observed problem to a verified result quickly.
We will cover the most common failure modes, including bridge networking misconfigurations, overlay network issues in Swarm, DNS resolution failures, port publishing problems, and IPv6 mishaps. For each, we show how to diagnose the issue using standard Docker commands, understand the root cause, apply the minimal safe fix, and verify the outcome. The goal is operational safety: observe before changing, limit the blast radius, use placeholders instead of secrets, and document recovery steps.
Throughout the article, we emphasize a systematic approach:
- Inventory the environment: know the Docker version, topology, and current state.
- Read-only diagnostics: use
docker network inspect,docker logs,docker exec, and other commands to gather evidence. - Minimal change: adjust one scoped configuration item at a time.
- Verify: confirm the fix with a specific command and expected output.
By the end, you will have a set of repeatable troubleshooting procedures and a checklist to prevent recurring networking problems.
Version and Environment Inventory
Before diving into fixes, establish a baseline. Knowing your Docker version, storage driver, network plugins, and container runtime helps you avoid applying advice meant for a different setup. Run the following commands and record the output:
# Docker version
$ docker version --format '{{.Server.Version}}'
24.0.7
# Docker info (focus on network-relevant sections)
$ docker info --format '{{json .Plugins.Network}}'
["bridge","host","overlay","macvlan"]
# List running containers with their networks
$ docker ps --format 'table {{.Names}} {{.Networks}} {{.Ports}}'
NAMES NETWORKS PORTS
web bridge 0.0.0.0:8080->80/tcp
db myapp_default
For Compose projects, use docker compose ps and inspect the generated network:
$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
myapp_web_1 "docker-entrypoint.s…" web running 0.0.0.0:8080->80/tcp
myapp_db_1 "docker-entrypoint.s…" db running 5432/tcp
$ docker network ls | grep myapp
NETWORK ID NAME DRIVER SCOPE
abc123def456 myapp_default bridge local
If you suspect a network plugin issue, list all networks with their drivers and scope:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
1234567890ab bridge bridge local
cdef12345678 host host local
90abcdef1234 none null local
A production-like local test should include a restart test: stop the container, recreate it, and confirm the application still sees the expected network and files. If connectivity breaks after a restart, you likely have a configuration that depends on ephemeral container IPs or a missing network definition.
Common Error 1: Container Cannot Reach the Internet or External Hosts
Symptom
A container cannot ping an external IP (e.g., 8.8.8.8) or curl a public URL. The error might be ping: bad address or curl: (6) Could not resolve host, indicating DNS or routing failure.
Diagnosis
Start by checking the container's network settings:
$ docker exec mycontainer ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
If the container has no IP or the interface is down, something is wrong with the network creation. Check the container's network attachment:
$ docker inspect --format '{{json .NetworkSettings.Networks}}' mycontainer
{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"NetworkID":"1234567890ab","EndpointID":"","Gateway":"","IPAddress":"","IPPrefixLen":0,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"","DriverOpts":null}}
An empty IPAddress suggests the container did not join the network properly. Attempt to connect it explicitly:
$ docker network connect bridge mycontainer
If the container still has no connectivity, inspect the Docker daemon's DNS settings. The daemon uses the host's /etc/resolv.conf by default, but you can override it:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "1234567890ab",
"Created": "2024-01-01T00:00:00.000000000Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"...": {}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
If "Internal": true, the network is isolated from external traffic. If DNS resolution fails, check the container's /etc/resolv.conf:
$ docker exec mycontainer cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0
The embedded DNS server at 127.0.0.11 should be present. If not, the container was started with --dns or --dns-search overrides that may be incorrect.
Fix
- If the container is on a custom network with
internal: true, either recreate the network without that flag or connect the container to an external network. - If DNS is misconfigured, start the container with explicit DNS servers:
$ docker run -d --name mycontainer --dns 8.8.8.8 --dns 1.1.1.1 myimage
- If the default bridge network is causing issues, create a user-defined bridge network, which provides automatic DNS resolution between containers:
$ docker network create mynet
$ docker run -d --name mycontainer --network mynet myimage
- Verify connectivity:
$ docker exec mycontainer ping -c 4 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=18.6 ms
...
Common Error 2: Containers Cannot Communicate with Each Other on a User-Defined Bridge Network
Symptom
Two containers on the same user-defined bridge network cannot resolve each other by name or connect via IP. For example, a web container cannot reach db at db:5432.
Diagnosis
First, confirm both containers are on the same network:
$ docker network inspect mynet
[
{
"Name": "mynet",
"Id": "...",
"Containers": {
"container1_id": {
"Name": "web",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"container2_id": {
"Name": "db",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
}
}
]
If one container is missing, connect it:
$ docker network connect mynet web
Check if the containers can ping each other by IP:
$ docker exec web ping -c 4 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.123 ms
...
If IP ping works but name resolution fails, test with nslookup or getent:
$ docker exec web nslookup db
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: db
Address: 172.18.0.3
If nslookup fails, the embedded DNS server may be having issues, or the container's /etc/resolv.conf may not point to 127.0.0.11.
A common mistake is using the default bridge network, which does not provide automatic DNS resolution. On the default bridge, containers can only communicate via IP addresses (unless --link is used, which is deprecated).
Fix
- Create a user-defined bridge network and attach both containers:
$ docker network create mynet
$ docker network connect mynet web
$ docker network connect mynet db
- Alternatively, recreate the containers with the network specified at startup:
$ docker run -d --name web --network mynet webimage
$ docker run -d --name db --network mynet dbimage
- Test name resolution again:
$ docker exec web ping -c 1 db
PING db (172.18.0.3) 56(84) bytes of data.
64 bytes from db.mynet (172.18.0.3): icmp_seq=1 ttl=64 time=0.089 ms
Common Error 3: Port Mapping Not Working or Port Already in Use
Symptom
A container is started with -p 8080:80, but accessing localhost:8080 fails, or the container fails to start with Bind for 0.0.0.0:8080 failed: port is already allocated.
Diagnosis
Check if the port is already in use on the host:
$ sudo ss -tulpn | grep :8080
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("docker-proxy",pid=1234,fd=4))
Another container may be using the same port. List port mappings:
$ docker ps --format '{{.Names}} {{.Ports}}'
web1 0.0.0.0:8080->80/tcp
web2 0.0.0.0:8080->80/tcp # This will fail to start
If you are using a firewall, ensure the port is allowed. Also, check if the container process is actually listening on the container's port:
$ docker exec web1 netstat -tulpn | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master p
Fix
- Use a different host port:
$ docker run -d --name web2 -p 8081:80 webimage
- Or use dynamic port mapping and query the assigned port:
$ docker run -d --name web2 -P webimage
$ docker port web2
80/tcp -> 0.0.0.0:49153
- If a port must be freed, identify and stop the process using it, then restart the container.
Common Error 4: Overlay Network Issues in Docker Swarm
Symptom
In a Swarm cluster, services on different nodes cannot communicate over an overlay network. Errors like No route to host or name resolution failure occur.
Diagnosis
First, ensure the overlay network exists and is attached to the services:
$ docker network ls | grep overlay
NETWORK ID NAME DRIVER SCOPE
xyz123abc456 myoverlay overlay swarm
$ docker service inspect --format '{{json .Spec.TaskTemplate.Networks}}' myservice
[{"Target":"xyz123abc456"}]
Check that all nodes have the necessary ports open for overlay networking: TCP 2377 for cluster management, TCP/UDP 7946 for node communication, and UDP 4789 for VXLAN data.
On each node, verify the VXLAN interface exists:
$ ip link show type vxlan
10: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br0 state UNKNOWN mode DEFAULT group default
link/ether 02:42:... brd ff:ff:ff:ff:ff:ff
If the VXLAN interface is missing or the MTU is incorrect, it can cause fragmentation and connectivity issues.
Fix
- Ensure firewall rules allow the required ports.
- If MTU issues are suspected, adjust the MTU on the docker daemon or network. For example, if the underlying network has an MTU of 1400, set the Docker MTU to 1400:
$ sudo dockerd --mtu 1400
Or set it per network:
$ docker network create -d overlay --opt com.docker.network.driver.mtu=1400 myoverlay
- Restart the Docker daemon on affected nodes.
Common Error 5: DNS Resolution Failures for Custom Domains
Symptom
A container cannot resolve a custom internal domain, e.g., api.internal.example.com.
Diagnosis
Check the container's DNS configuration:
$ docker exec mycontainer cat /etc/resolv.conf
search mydomain.local
nameserver 127.0.0.11
options ndots:0
If the custom domain is served by an external DNS server, the container may not be querying it. Test with nslookup using the specific server:
$ docker exec mycontainer nslookup api.internal.example.com 10.0.0.53
If that works but default resolution does not, the Docker DNS may not forward to the right server.
Fix
Start the container with the --dns and --dns-search options:
$ docker run -d --name mycontainer --dns 10.0.0.53 --dns 8.8.8.8 --dns-search mydomain.local myimage
Alternatively, configure the Docker daemon to use a custom DNS server globally by editing /etc/docker/daemon.json:
{
"dns": ["10.0.0.53", "8.8.8.8"],
"dns-search": ["mydomain.local"]
}
Then restart Docker:
$ sudo systemctl restart docker
Common Error 6: IPv6 Configuration Problems
Symptom
Containers do not get IPv6 addresses or cannot communicate over IPv6.
Diagnosis
Check if IPv6 is enabled on the network:
$ docker network inspect bridge | grep EnableIPv6
"EnableIPv6": false,
By default, IPv6 is disabled. If you need IPv6, you must enable it in the daemon configuration and create networks with IPv6 subnets.
Fix
- Edit
/etc/docker/daemon.jsonto enable IPv6 and set a fixed CIDR:
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64"
}
- Restart Docker:
$ sudo systemctl restart docker
- Create a network with IPv6 support:
$ docker network create --ipv6 --subnet=2001:db8:1::/64 myipv6net
- Run a container on that network and check its IPv6 address:
$ docker run -d --name ipv6test --network myipv6net alpine sleep 300
$ docker exec ipv6test ip -6 addr show eth0
2: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
inet6 2001:db8:1::242:ac11:2/64 scope global nodad
valid_lft forever preferred_lft forever
Common Pitfalls and How to Avoid Them
- Using the default bridge network for production. The default bridge lacks automatic service discovery and isolation. Always create user-defined networks for applications.
- Why it happens: convenience;
docker runwithout--networkdefaults to bridge. - How to avoid: define networks in Compose files or create custom networks explicitly.
- Hard-coding container IPs. Container IPs can change after recreation. Rely on DNS names instead.
- Why it happens: Developers may inspect and copy IPs.
- How to avoid: use service names; if needed, assign static IPs via
--ipon a user-defined network.
- Ignoring MTU mismatches. Overlay networks over VPNs or certain cloud providers may require lower MTU.
- Why it happens: default MTU 1500 may not work if underlying network has lower MTU.
- How to avoid: test with
ping -M do -s 1472 <host>to discover max MTU and configure accordingly.
- Not cleaning up unused networks. Unused networks can clutter the environment and cause confusion.
- Why it happens: forgetting to remove networks after experiments.
- How to avoid: periodically run
docker network prune.
- Overlooking firewall rules. For Swarm or multi-host setups, missing firewall ports cause mysterious failures.
- Why it happens: assuming all traffic is allowed.
- How to avoid: document required ports and verify with
nc -zv <host> <port>.
Operations Checklist
Use this checklist before and after making network changes:
- [ ] Record current state:
docker network ls,docker ps,docker info. - [ ] Identify the error: collect exact error messages from logs and commands.
- [ ] Isolate the issue: test connectivity with
ping,curl,nslookup, andtraceroute. - [ ] Check network configuration:
docker network inspect <network>. - [ ] Check DNS settings:
cat /etc/resolv.confinside container. - [ ] Check port mappings:
docker port <container>. - [ ] Verify firewall rules: ensure required ports are open.
- [ ] Make one change at a time and test after each change.
- [ ] Document the change and rollback plan.
- [ ] Verify the fix: repeat the original failing command and confirm success.
- [ ] Update monitoring and alerting if necessary.
Conclusion
Docker networking errors can be daunting, but a systematic approach simplifies troubleshooting. By establishing a baseline, using the right diagnostic commands, understanding common failure patterns, and applying minimal fixes with verification, you can resolve most networking issues quickly. Always prefer user-defined bridge networks for container-to-container communication, avoid hard-coding IPs, and pay attention to DNS and MTU settings. Use the operations checklist to prevent future problems and ensure a reliable container environment. With practice, you will navigate Docker networking with confidence.