← Back to Labs / Docker

Fix: Docker Container Outbound HTTPS Timeout (Host Works, MTU Bridge Fix)

OpsNexusAI Engineering
8 min read

Fix: Docker Container Outbound HTTPS Timeout (Host Works, MTU Bridge Fix)

A Docker container cannot perform outbound HTTPS requests (e.g., curl -I https://huggingface.co or apt-get update hangs indefinitely or times out), while the host machine connects to the internet without issues. Small HTTP requests may succeed, but larger packet transfers hang after the initial TCP handshake.


Quick Fix: MTU Size Mismatch on docker0 Bridge

The most common root cause in cloud VPS environments (Hetzner, AWS, OpenStack, Wireguard/Tailscale VPN tunnels) is an MTU (Maximum Transmission Unit) mismatch. The host physical interface uses an MTU of 1420 or 1450, while Docker defaults to 1500, causing packet fragmentation drops during TLS key exchange.

Update Docker daemon MTU in /etc/docker/daemon.json:

{
  "mtu": 1420
}

Then restart Docker:

sudo systemctl restart docker

Symptoms

  1. Hangs on TLS Client Hello: Running curl -v https://example.com inside the container connects (TCP SYN/ACK succeeds), but hangs immediately during * TLSv1.3 (OUT), TLS handshake, Client hello (1):.
  2. Host Connection Works Perfectly: curl https://example.com executed on the host server succeeds in milliseconds.
  3. Small Payloads Pass, Large Payloads Hang: ping 8.8.8.8 and curl http://example.com succeed, but downloading a 10MB file or installing packages via pip or apt stalls at 0%.

Root Causes

Host Interface (MTU 1420 - e.g. Wireguard / Cloud VPC)
┌─────────────────────────────────────────────────────────────┐
│  Host Network MTU: 1420 bytes                               │
└──────────────────────────────▲──────────────────────────────┘
                               │ (Packets > 1420 dropped without ICMP)
┌──────────────────────────────▼──────────────────────────────┐
│  Docker Bridge (docker0) Default MTU: 1500 bytes            │
│  * Large TLS Certificate Packet (1460 bytes) is DROPPED!    │
└─────────────────────────────────────────────────────────────┘
  1. MTU Mismatch (Path MTU Blackhole): The host’s physical network or VPN tunnel uses an MTU smaller than standard Ethernet (1500). When the container sends a 1500-byte packet with the DF (Don’t Fragment) bit set, intermediate routers drop it without returning ICMP fragmentation notifications.
  2. DNS Server Routing Failure: systemd-resolved on the host binds to 127.0.0.53. If Docker is not passing proper upstream DNS servers, containerized DNS queries timeout.
  3. iptables FORWARD Policy Drop: The host firewall or ufw default forward policy is set to DROP, blocking container NAT packets.

Step-by-Step Diagnostic & Permanent Remediation

1. Identify Host Network MTU

Check the active MTU of your host server’s primary outbound interface:

ip link show | grep -E 'mtu|state UP'

Example Output:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1420 qdisc fq_codel state UP
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state DOWN

Notice eth0 is 1420 while docker0 is 1500.


2. Configure Global Docker Daemon MTU

Edit /etc/docker/daemon.json (create it if it does not exist):

{
  "mtu": 1420,
  "dns": ["1.1.1.1", "8.8.8.8"]
}

Restart the Docker daemon to apply changes to the default docker0 bridge:

sudo systemctl restart docker

3. Configure Custom Docker Compose Networks

If your containers run inside a custom bridge network defined in docker-compose.yml, specify the MTU explicitly in the network driver options:

version: '3.8'

services:
  ai-app:
    image: python:3.11-slim
    command: curl -Iv https://huggingface.co
    networks:
      - custom_mesh

networks:
  custom_mesh:
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: "1420"

4. Fix Host iptables / UFW Forwarding Rules

If MTU matches but outbound packets are still blocked:

# Allow packet forwarding in sysctl
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.d/99-docker-forward.conf

# If using UFW, set default forward policy to ACCEPT in /etc/default/ufw:
# DEFAULT_FORWARD_POLICY="ACCEPT"
sudo ufw reload

Verification Test

Test MTU packet transmission from inside a temporary container:

# 1. Test ping without fragmentation
docker run --rm alpine ping -c 3 -s 1390 -M do 1.1.1.1

# 2. Test full HTTPS TLS handshake and certificate download
docker run --rm curlimages/curl -Iv https://huggingface.co

If both commands return immediately with HTTP/2 200 or HTTP/1.1 200 OK, the MTU bottleneck is resolved.


OpsNexusAI Engineering

Verified Lab Publication

OpsNexusAI is a technical laboratory dedicated to sovereign AI infrastructure. Every implementation guide and architectural blueprint published here is tested on physical hardware and isolated networks. Our team specializes in the deployment of private LLMs, network hardening with OPNsense, and enterprise-grade automation patterns.


Join the OpsNexus Brief

Get technical teardowns on sovereign AI architectures delivered to your inbox.