Scenario / Questions

I’m building a container to tune kernel settings for a load balancer. I’d prefer to deploy those changes to the host in an image using a single privileged container. For example:

docker run --rm --privileged ubuntu:latest sysctl -w net.core.somaxconn=65535

In testing the changes take effect but only for that container. I was under the impression that with a fully privileged container changes to /proc would actually change the underlying OS.

$docker run --rm --privileged ubuntu:latest \
    sysctl -w net.core.somaxconn=65535
net.core.somaxconn = 65535

$ docker run --rm --privileged ubuntu:latest \
    /bin/bash -c "sysctl -a | grep somaxconn"
net.core.somaxconn = 128

Is this how privileged containers are supposed to work?

Am I just doing something silly?

What is the best way to make lasting changes?

Version Info:

Client version: 1.4.1
Client API version: 1.16
Go version (client): go1.3.3
Git commit (client): 5bc2ff8
OS/Arch (client): linux/amd64
Server version: 1.4.1
Server API version: 1.16
Go version (server): go1.3.3
Git commit (server): 5bc2ff8

Example command with mounted /proc:

$ docker run -v /proc:/proc ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

$ docker run -v /proc:/proc --privileged ubuntu:latest \
    /bin/bash -c "sysctl -p /updates/sysctl.conf"
net.ipv4.ip_local_port_range = 2000 65000

$ docker run -v /proc:/proc ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

$ docker run -v /proc:/proc --privileged ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

Find below all possible solutions or suggestions for the above questions..

Suggestion: 1

This particular setting falls under the influence of the network namespace that docker runs in.

As a general rule /proc does alter settings that are relevent systemwide, technically speaking however you are altering settings in /proc/net which returns results on a per network namespace basis.

Note that /proc/net is actually a symlink to /proc/self/net as it really does reflect the settings of the namespace that you are doing the work in.

Suggestion: 2

Docker 1.12+ has native support for tweaking sysctl values inside the containers. Here is an excerpt from the documentation:

Configure namespaced kernel parameters (sysctls) at runtime

The –sysctl sets namespaced kernel parameters (sysctls) in the container. For example, to turn on IP forwarding in the containers network namespace, run this command:

docker run --sysctl net.ipv4.ip_forward=1 someimage

Using your example, the correct way to raise net.core.somaxconn would be:

docker run ... --sysctl net.core.somaxconn=65535 ...

Suggestion: 3

The privileged container is still using its own process namespace for /proc. What you can do is to mount the real /proc inside the container:

docker run --rm --privileged -v /proc:/host-proc ubuntu:latest \
  'echo 65535 > /host-proc/sys/net/core/somaxconn'

Suggestion: 4

This works for me with Docker 1.5.0:

docker run --privileged --net=host --rm ubuntu:latest /bin/sh -c \
   'echo 65535 > /proc/sys/net/core/somaxconn'