Docker is a powerful tool that has revolutionized the way developers build, package, and distribute applications. However, like any technology, it comes with its own set of challenges. One lesser-known but impactful issue arises due to Docker's default handling of Maximum Transmission Unit (MTU) settings.

MTU, an essential network parameter, defines the largest size of a data packet that can be transmitted in a single network layer transaction. Docker, by default, sets this parameter to 1500 bytes, irrespective of the underlying network's MTU configuration. This mismatch can lead to unexpected connectivity issues, affecting the performance of your Docker containers and the applications running within them.

This tutorial delves into this Docker MTU issue, providing practical ways to detect it and a straightforward solution on how to fix it, particularly for users running Docker on Ubuntu. Let's explore this below-the-radar issue that could be impacting your Docker experience and how to navigate it efficiently.

Issues with Docker's default MTU and its effects

Docker is recognized to exhibit a peculiar behavior where it appears to disregard the network's established Maximum Transmission Unit (MTU) - a parameter that denotes the largest possible size of a data packet that can be transmitted. Instead, Docker automatically sets its default MTU to 1500 bytes.

The MTU is a critical element used by the Internet's Transmission Control Protocol (TCP) to determine the maximum size of each packet that is part of any given transmission. This value of 1500 bytes is typically associated with the Ethernet protocol, which allows a packet of this size as the maximum limit.

Consequently, this leads to scenarios where a Docker container anticipates sending larger packets than what the underlying network is configured to handle. In these instances, the excess parts of the packet are truncated, leading to potential issues in communication and data transmission.

How to detect the MTU issue

Here's an example using the output from running the command ip a:

2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc pfifo_fast state UP group default qlen 1000
    link/ether fb:1a:3e:47:80:62 brd ff:ff:ff:ff:ff:ff
    inet 10.17.228.5/24 brd 10.35.228.255 scope global ens3
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:83:20:dc:cc brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

The important parts are you can see that ens3 (the default network interface) has an MTU of 1450, but Docker created the docker0 interface with a higher MTU of 1500.

The effect of this is that you may get timeouts when connecting to internet services (such as package updates/downloads, Ruby gem installation, etc) or even that files download but don't have the correct size/contents.

How to fix the MTU issue with Ubuntu

Fortunately the fix is quite easy, you need to add a parameter to your launch script for Docker to specify/override the MTU. Using Ubuntu 22.04 for example, the file to edit as root is /lib/systemd/system/docker.service. You need to change the line looking like this:

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

to look like this:

ExecStart=/usr/bin/dockerd --mtu 1450 -H fd:// --containerd=/run/containerd/containerd.sock

Note: It's quite fine to use the same value as the default network interface (in our example and for our infrastructure 1450), it just can't be higher.

If you are using docker-compose to launch your instances, you will also need to change some config to ensure that they launch with a 1450 MTU.

Your Docker compose file should look something like this:

networks:
  default:
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: 1450

After that, you need to restart Docker and all will be well with your networking:

sudo systemctl daemon-reload
sudo service docker restart

Summary

This article has provided a solution for an issue caused by Docker ignoring the network's MTU setting, resulting in connectivity errors. By modifying the launch script and configuring the Docker-compose, the MTU can be set correctly. Don't forget to restart Docker after editing the launch script to apply the changes.

Additional resources

If you want to continue learning about this topic, check out some of the below resources:

  • Container Network Interfaces: A comprehensive overview of container network interfaces, an essential aspect of networking within Kubernetes.
  • IP Packets: Delve into the concept of IP packets. It provides a great foundational understanding for anyone interested in networking.
  • IP Addressing: Explains IP addressing and covers both IPv4 and IPv6 addressing schemes.
  • Networking Category: A collection of tutorials on Networking. It includes several topics related to networking, providing a broad range of information for both beginners and advanced users.