moby: Dockerd `mtu` configuration option does not work on Windows Docker

Description

It is not possible to change default MTU values which will be used inside new containers.

Steps to reproduce the issue:

  1. Change mtu value in your daemon.json as described here: https://docs.docker.com/engine/reference/commandline/dockerd/ for example 1398
  2. Restart the host
  3. Start new container
  4. Execute the command inside container docker exec mtutest powershell netsh interface ipv4 show interfaces

Describe the results you received:

I still see that MTU for “vEthernet …” is still 1500

Describe the results you expected:

I expected it will be 1398.

I did not find in the codebase that Docker uses this configuration option for Windows so most likely it is a documentation error? But I am not 100% sure, maybe I missed something.

Does anybody now how we else can change the default MTU value which is set to every internal container’s vEthernet interface?

Thanks!

Additional information you deem important (e.g. issue happens only occasionally):

Output of docker version:

Client:
 Version:      17.10.0-ce
 API version:  1.33
 Go version:   go1.8.3
 Git commit:   f4ffd25
 Built:        Tue Oct 17 19:00:02 2017
 OS/Arch:      windows/amd64

Server:
 Version:      17.10.0-ce
 API version:  1.33 (minimum version 1.24)
 Go version:   go1.8.3
 Git commit:   f4ffd25
 Built:        Tue Oct 17 19:09:12 2017
 OS/Arch:      windows/amd64
 Experimental: false

Output of docker info:

Containers: 14
 Running: 13
 Paused: 0
 Stopped: 1
Images: 94
Server Version: 17.10.0-ce
Storage Driver: windowsfilter
 Windows:
Logging Driver: json-file
Plugins:
 Volume: local
 Network: ics l2bridge l2tunnel nat null overlay transparent
 Log: awslogs etwlogs fluentd json-file logentries splunk syslog
Swarm: inactive
Default Isolation: process
Kernel Version: 10.0 14393 (14393.1770.amd64fre.rs1_release.170917-1700)
Operating System: Windows Server 2016 Datacenter
OSType: windows
Architecture: x86_64
CPUs: 64
Total Memory: 488GiB
Name: ...
ID: ...
Docker Root Dir: E:\docker_storage_1_13
Debug Mode (client): false
Debug Mode (server): true
 File Descriptors: -1
 Goroutines: 109
 System Time: 2017-12-03T21:44:18.6526331+01:00
 EventsListeners: 1
Username: aureadev
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 2
  • Comments: 24

Commits related to this issue

Most upvoted comments

Same issue here on Windows Server 1803, all updates running Docker EE 18.09.6. Setting mtu in daemon.json does not work.

@davidmohar: I’m not sure if this is actually working correctly myself. I changed the MTU to 1400 in daemon.json and then ran ip addr in an Alpine container on one of the cluster nodes:

root@worker-0:~# docker run -it --rm alpine ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
36: eth0@if37: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1400 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

As you can see, this reports MTU=1400 for eth0, so I figured this was working.

The interesting thing is that when you connect the container to a new Docker network, the MTU is set back to 1500:

root@worker-0:~# docker network create foo-net
9f396dadceedac15aaee838e60b31120a4c43fa9c39aa3ecca37772bd61992a1

root@worker-0:~# docker run -it --rm --network foo-net alpine ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
39: eth0@if40: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
       valid_lft forever preferred_lft forever

It appears that the daemon.json MTU setting does not apply to Docker networks. You need to set this explicitly:

root@worker-0:~# docker network create --opt com.docker.network.driver.mtu=1400 bar-net
d23f6c6fe6796fd14683d4d63ff72e56dd5977d8057d7acb0fdd7a105675c6d8

root@worker-0:~# docker run -it --rm --network bar-net alpine ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
42: eth0@if43: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1400 qdisc noqueue state UP
    link/ether 02:42:ac:14:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.2/16 brd 172.20.255.255 scope global eth0
       valid_lft forever preferred_lft forever

In this example, I created a new network that explicitly set the MTU to 1400 and you can see that reported in the container.

This seems kind of broken because this means that when MTU is important, you’d need to explicitly update any docker network related scripts and compose/stack files to specify the MTU rather than having these inherited from the daemon config which would be a pain when trying to deploy things to environments that required different MTUs.

I just attended KubeCon 2018 this week and I’m moving on to stock Kubernetes now. Swarm looks like a dead end and Kubernetes as matured a lot since the last time I looked at it and hopefully won’t have issues like these.

I’ve confirmed that Set-NetIPInterface can be invoked on the host to update the MTU of a running container, e.g.:

Set-NetIPInterface -IncludeAllCompartments -InterfaceAlias "vEthernet (Ethernet) 2" -NlMtuBytes 1234

It seems plausible that the moby code that creates Windows containers could be changed to: 1) get the new container’s vEthernet interface name/ID, then 2) immediately invoke the Set-NetIPInterface command/API to change the container interface’s MTU, before returning or letting anything else happen in the container.

Would this be a good idea? If anyone has pointers to where in the moby code these changes could be made, that would be helpful…