Tech Expert & Vibe Coder

With 15+ years of experience, I specialize in self-hosting, AI automation, and Vibe Coding – building applications using AI-powered tools like Google Antigravity, Dyad, and Cline. From homelabs to enterprise solutions.

Debugging Docker Bridge Network MTU Issues Causing Intermittent Container Timeouts

When Containers Stop Talking: My Journey Through Docker MTU Hell

I run a mix of self-hosted services on Docker—monitoring tools, automation workflows, databases, and web apps. For months, everything worked fine. Then one day, I started seeing random timeouts. Not everywhere. Not consistently. Just enough to make me question my sanity.

A container would fail to reach another service. Five minutes later, it worked. Then it failed again. Logs showed nothing useful—just connection timeouts. No errors. No pattern I could see.

It took me two frustrating weeks to track down the real cause: MTU mismatch on Docker’s bridge network.

What Actually Happened

My setup at the time:

  • Proxmox host running multiple VMs
  • One VM dedicated to Docker containers
  • PPPoE connection to my ISP (this matters)
  • Default Docker bridge network with standard 1500 MTU

The symptoms were maddening:

  • Small HTTP requests worked fine
  • Larger API responses timed out
  • Database queries failed unpredictably
  • DNS lookups worked, but actual data transfer didn’t

What made it worse: I could ping containers from each other. I could curl small endpoints. Everything looked fine at first glance.

How I Found the Problem

I started with the usual checks. Verified containers were on the same network. Checked DNS resolution. Looked at firewall rules. All good.

Then I tried something different. I ran a ping test with varying packet sizes:

docker exec my-container ping -M do -s 1400 target-container

This worked fine. But when I increased the size:

docker exec my-container ping -M do -s 1472 target-container

Timeouts. Every single time.

That’s when it clicked. The -M do flag prevents packet fragmentation. The 1472-byte payload, plus 28 bytes of IP and ICMP headers, equals exactly 1500 bytes—the standard MTU.

My packets were being silently dropped somewhere in the network path.

Why This Happened

My ISP uses PPPoE, which adds an 8-byte header to every packet. That means the effective MTU on my WAN connection is 1492 bytes, not 1500.

Docker’s default bridge network uses 1500 MTU. When a container tried to send a packet larger than 1492 bytes to an external service (or even to another container routing through certain network paths), the packet got dropped because fragmentation wasn’t allowed.

The reason it was intermittent: small packets fit fine. Only larger transfers—like JSON responses from APIs or database result sets—hit the MTU ceiling.

How I Fixed It

I needed to lower Docker’s bridge MTU to match my actual network capacity. Here’s what I did:

First, I checked the current MTU on Docker’s bridge:

docker network inspect bridge | grep -i mtu

It showed 1500, as expected.

I created a new bridge network with a lower MTU:

docker network create 
  --driver bridge 
  --opt com.docker.network.driver.mtu=1492 
  lowmtu

Then I moved my containers to this new network. For containers defined in Docker Compose, I updated the compose file:

version: '3.8'
services:
  my-service:
    image: my-image
    networks:
      - lowmtu

networks:
  lowmtu:
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: "1492"

After restarting the containers, the timeouts stopped. Completely.

What I Learned About MTU

MTU (Maximum Transmission Unit) is the largest packet size a network can transmit without fragmentation. If a packet exceeds the MTU at any point in its path, it either gets fragmented or dropped.

In my case, the path was:

  1. Container (MTU 1500)
  2. Docker bridge (MTU 1500)
  3. Host network interface (MTU 1500)
  4. PPPoE connection (MTU 1492)

The mismatch at step 4 caused the problem.

What’s tricky: many protocols handle this gracefully through Path MTU Discovery. But when firewalls block ICMP messages (which signal “packet too big”), PMTUD fails silently. That’s exactly what was happening in my setup.

How to Debug This Yourself

If you’re seeing similar intermittent timeouts, here’s how I’d approach it:

1. Test with different packet sizes

docker exec container-name ping -M do -s 1400 target
docker exec container-name ping -M do -s 1472 target

If smaller packets work but larger ones fail, you likely have an MTU issue.

2. Check your actual network MTU

ip link show | grep mtu

Look at your WAN interface. If you’re on PPPoE, DSL, or certain VPN setups, it’s probably not 1500.

3. Verify Docker’s bridge MTU

docker network inspect bridge | grep -i mtu

Compare this to your actual network MTU. If Docker’s is higher, you have a mismatch.

4. Test with tcpdump

docker exec container-name tcpdump -i eth0 -n 'icmp'

Run this while testing connectivity. Look for “frag needed” ICMP messages. If you see them, it confirms MTU issues.

Other Scenarios I Encountered

After fixing my main setup, I ran into MTU problems in two other places:

VPN tunnels: When I set up WireGuard for remote access, I had to lower the MTU on both the VPN interface and Docker networks. WireGuard adds its own overhead, so I ended up using 1420 MTU for containers that needed to work over VPN.

Nested virtualization: Running Docker inside a Proxmox VM that itself runs on a virtualized network added multiple layers of encapsulation. I had to drop the MTU even further—down to 1450—to account for all the overhead.

What Didn’t Work

Before I figured out the MTU issue, I tried a lot of things that seemed reasonable but didn’t help:

  • Adjusting Docker’s DNS settings
  • Changing the bridge network subnet
  • Disabling IPv6 on containers
  • Tweaking TCP keepalive settings
  • Rebuilding containers from scratch

None of these addressed the real problem. They just wasted time.

I also tried setting MTU on individual containers using --network-opt, but that doesn’t actually work. MTU must be set at the network level, not per container.

When to Suspect MTU Issues

Based on my experience, consider MTU problems if you see:

  • Timeouts only on larger data transfers
  • Small requests work, large ones fail
  • Inconsistent behavior that seems random
  • Problems that appear after network changes (new ISP, VPN, etc.)
  • Issues that affect some protocols but not others

If basic connectivity tests (ping, DNS) work fine but actual application traffic fails, MTU is a strong candidate.

My Current Setup

I now run all my Docker containers on a custom bridge network with MTU set to 1492. This matches my PPPoE connection and leaves a small buffer for any additional overhead.

For containers that need to work over WireGuard VPN, I use a separate network with MTU 1420.

I also added MTU testing to my monitoring setup. A simple script pings key services with large packets every few minutes. If it starts failing, I get an alert before users notice problems.

Key Takeaways

MTU issues are frustrating because they’re invisible until they’re not. You can’t see them in logs. They don’t show up in basic connectivity tests. They just cause random failures that make you question everything.

The lesson I learned: when debugging network problems, test with different packet sizes early. Don’t assume MTU 1500 works everywhere. It often doesn’t.

If you’re running Docker on PPPoE, DSL, or through VPN tunnels, check your MTU settings before you waste weeks troubleshooting phantom problems like I did.

Leave a Comment

Your email address will not be published. Required fields are marked *