Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Docker-Desktop for Windows, how can sysctl parameters be configured to permeate a reboot?

Running elasticsearch in win10 [wsl2] docker-desktop requires to increase mmap counts to 262144 through sysctl -w vm.max_map_count=262144

C:\Users\<username>>wsl -d docker-desktop
<hostname>:/tmp/docker-desktop-root/mnt/host/c/Users/<username># sysctl -w vm.max_map_count=262144

In an answer to this question and elastic's doc it is suggested to accordingly update the vm.max_map_count in /etc/sysctl.conf to set this value permanent, i. e. making it survive the reboot.

Please note the output below, showing the effective mmap count did not adapt to the value defined in sysctl.conf, after my attempt to follow this suggestion and after reboot.

Why didn't it?

PS C:\Users\<username>> wsl -d docker-desktop
<hostname>:/tmp/docker-desktop-root/mnt/host/c/Users/<username># sysctl vm.max_map_count
vm.max_map_count = 65530
<hostname>:/tmp/docker-desktop-root/mnt/host/c/Users/<username># cd /etc
<hostname>:/etc# cat sysctl.conf
# content of this file will override /etc/sysctl.d/*
vm.max_map_count=262144

Considering to have changed the wrong sysctl.conf in etc/ I tried to change the sysctl.conf in <hostname>:/tmp/docker-desktop-root/etc#. This was not allowed as this is a Read-only file system.

Can/should this be parameterized in .wslconfig instead, if so, how?

Using openSUSE Leap 15.2 instead of Win10's PowerShell did not change the outcome.

<username@hostname>:~> sysctl vm.max_map_count
vm.max_map_count = 65530
<username@hostname>:~> cat /etc/sysctl.conf
####
#
# /etc/sysctl.conf is meant for local sysctl settings
#
# sysctl reads settings from the following locations:
#   /boot/sysctl.conf-<kernelversion>
#   /lib/sysctl.d/*.conf
#   /usr/lib/sysctl.d/*.conf
#   /usr/local/lib/sysctl.d/*.conf
#   /etc/sysctl.d/*.conf
#   /run/sysctl.d/*.conf
#   /etc/sysctl.conf
#
# To disable or override a distribution provided file just place a
# file with the same name in /etc/sysctl.d/
#
# See sysctl.conf(5), sysctl.d(5) and sysctl(8) for more information
#
####
vm.max_map_count=262144

Notably, the header in the above sysctl.conf file refers to a /boot/sysctl.conf-<kernelversion>. Taking into account, mmap count might need to be defined in this file in order to be considered when booting, I tried to set the required parameter there, but had no permission to do so.

<username@hostname>:/boot> sudo echo 'vm.max_map_count=262144' >> sysctl.conf-5.10.16.3-microsoft-standard-WSL2
-bash: sysctl.conf-5.10.16.3-microsoft-standard-WSL2: Permission denied

One of the known issues and limitations reported in openSUSE:WSL - openSUSE Wiki is

A system in WSL does not actually boot and does not use systemd. A proprietary Microsoft /init binary initializes the system. Therefore service management does not work like in a VM. It rather behaves like an interactive container.

Can anyone verify this to be the reason why parameterizing sysctl.conf cannot be an effective approach to the purpose at hand?

System

Host
OS: Microsoft Windows 10 Enterprise
Version: 10.0.18363 Build 18363 \

Docker
Client:
Version: 20.10.8
API version: 1.41
Go version: go1.16.6
Git commit: 3967b7d
Built: Fri Jul 30 19:54:02 2021
OS/Arch: linux/amd64
Plugins:
compose: Docker Compose (Docker Inc., v2.0.0-rc.2)
scan: Docker Scan (Docker Inc., v0.8.0)

Server:
Engine:
Version: 20.10.8
API version: 1.41 (minimum version 1.12)
Go version: go1.16.6
Git commit: 75249d8
Built: Fri Jul 30 19:52:10 2021
OS/Arch: linux/amd64
containerd:
Version: 1.4.9
GitCommit: e25210fe30a0a703442421b0f60afac609f950a3
runc:
Version: 1.0.1
GitCommit: v1.0.1-0-g4144b63
docker-init:
Version: 0.19.0
GitCommit: de40ad0 \

Kernel Version: 5.10.16.3-microsoft-standard-WSL2
Operating System: Docker Desktop
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 12.39GiB
Name: docker-desktop

like image 914
ToOolzZz Avatar asked Sep 16 '21 19:09

ToOolzZz


People also ask

Where is sysctl conf in Windows?

/etc/sysctl. conf.

Does sysctl persist after reboot?

Most commands do stick. However Lynis has repeatedly demonstrated four sysctl parameters are not sticking on reboot. sysctl -p does successfully apply them after the system has started.

What is sysctl conf?

conf is a simple file containing sysctl values to be read in and set by sysctl. The syntax is simply as follows: # comment ; comment token = value Note that blank lines are ignored, and whitespace before and after a token or value is ignored, although a value can contain whitespace within.

Is sysctl permanent?

Change the kernel behaviour with sysctl This is immediately applied, but will only last 'till the next boot, so it is not a permanent change.


1 Answers

Short answer:

In your Windows %userprofile% directory (typically C:\Users\<username>) create or edit the file .wslconfig with the following:

[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=262144"

Then exit any WSL instance, wsl --shutdown, and restart.

> sysctl vm.max_map_count
vm.max_map_count = 262144

More Detail:

You really have three (closely related) questions:

  • (Mainly) How to best persist this setting
  • Can it be done via .wslconfig?

    Can/should this be parameterized in .wslconfig instead, if so, how?

  • Why isn't /etc/sysctl.conf working to persist it?

    /etc/sysctl.conf to set this value permanent, i. e. making it survive the reboot .... Why didn't it?

We'll combine the first two, since the answer is "Yes, you can do it via .wslconfig.

This wasn't easy to find, since the change is fairly recent. It comes curtesy this answer.

Starting with kernel release 5.8, you can set sysctl values on the kernel command-line using the sysctl.* prefix to the value.

So as long as you have upgraded your WSL kernel (which I had not on two of my systems since wsl --update only recently was released in 21H1), you can set your %userprofile%\.wslconfig as above.


/etc/sysctl.conf

/etc/sysctl.conf to set this value permanent, i. e. making it survive the reboot .... Why didn't it?

There's a lot more to this section than is really needed since I went down this rabbit trail first and posted it as the original answer. But first, "why" it wasn't working ...

This is a known issue of sorts with WSL2.

While sysctl and Systemd/systemctl are two completely different things, in that issue therealkenc (of the Microsoft WSL team) points out that something must read and process /etc/sysctl.conf. In most Linux distributions, that's Systemd or the SysVInit scripts.

WSL, on the other, uses it's own /init in place of SysVInit or Systemd. The WSL init process does not (currently) have a mechanism for running services at startup, as you found in the openSUSE doc. So ... nothing reads and acts on /etc/sysctl.conf at startup.


The remainder of this answer includes some systcl.conf workarounds that aren't needed given we can do this with .wslconfig. This is left in just in case anyone finds it useful for some reason.

There are a few workarounds for this. All of them are going to involve finding a way to run sysctl -w vm.max_map_count=262144 (as root) automatically:

  • First, in Windows 11, WSL has a new feature to simplify this. Simply create/edit /etc/wsl.conf (via sudo) with:

    [boot]
    command="sysctl -w vm.max_map_count=262144"
    

    This will run at root each time the WSL instance starts. As far as I know, this will also work from within the docker-desktop instance, but I have not been able to test that.

    Important Note: Please back up your WSL instance using wsl --export, or at least backup your Docker volumes, images, and containers, before attempting this change. It's my experience that it is possible via a stalled boot command to completely prevent the instance from booting, with no recovery mechanism that I have (yet) found. Fortunately, I was working in a newly installed test instance, so I was able to wsl --unregister it (completely destroying it) without losing anything other than a few minutes.


For the many of us who will be on Windows 10 for some time to come, there are several options. Unfortunately I haven't been able to test these against Docker, but I've used similar techniques with other WSL instances in the past:

  • If Docker Desktop is set to run when you log in, then you could add a scheduled task (via Windows Task Scheduler) to also run at login. This would be a:

    • "Basic Task"
    • With the "Program" set to wsl.exe
    • And the Arguments set to -d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"

    Note that if the docker-desktop WSL instance terminates at any point, then the change will be lost until next reboot. However, because Docker Desktop is running at boot/login, the instance should remain up with this change in place.


  • Depending on your workflow, this may or may not fit. If you are using a separate WSL instance (e.g. Ubuntu) for development purposes, you can have that instance modify the docker-desktop instance when you start up.

    So that you don't have to type the sudo password each time you start up, use the following line in your .bashrc (or equivalent):

    wsl.exe -d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"
    

One final suggestion -- Submit a feature request to the Docker Desktop team. It would, IMHO, be easiest for Docker Desktop's startup process to read /etc/sysctl.conf and process it accordingly.

like image 145
NotTheDr01ds Avatar answered Nov 15 '22 20:11

NotTheDr01ds