Fix: Docker Container Outbound HTTPS Timeout (Host Works, MTU Bridge Fix)
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
- Hangs on TLS Client Hello:
Running
curl -v https://example.cominside the container connects (TCP SYN/ACK succeeds), but hangs immediately during* TLSv1.3 (OUT), TLS handshake, Client hello (1):. - Host Connection Works Perfectly:
curl https://example.comexecuted on the host server succeeds in milliseconds. - Small Payloads Pass, Large Payloads Hang:
ping 8.8.8.8andcurl http://example.comsucceed, but downloading a 10MB file or installing packages viapiporaptstalls 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! │
└─────────────────────────────────────────────────────────────┘
- 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.
- DNS Server Routing Failure:
systemd-resolvedon the host binds to127.0.0.53. If Docker is not passing proper upstream DNS servers, containerized DNS queries timeout. iptablesFORWARD Policy Drop: The host firewall orufwdefault forward policy is set toDROP, 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.
Related Guides & Blueprints
- OPNsense Firewall: Fix: OPNsense Blocking Docker VLAN Traffic
- Private AI Stack: Private AI Stack Architecture Blueprint
- GPU Container Toolkit: Fix: Ollama GPU Not Detected in Docker
OpsNexusAI Engineering
Verified Lab PublicationOpsNexusAI 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.