Using Docker-Desktop for Windows, how can sysctl parameters be configured to survive a reboot?
Asked Answered
A

2

22

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

Acetylide answered 16/9, 2021 at 19:43 Comment(0)
I
58

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

Alternative (updated) short answer:

WSL now supports Systemd with some additional configuration. If you choose to enable Systemd on WSL, then the "normal" methods for persisting the vm.max_map_count (and other parameters) in /etc/sysctl.conf will work. See this Community Wiki answer or my original version for the prerequisites and how to enable.


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?

At the time this question was written, this was a known issue of sorts with WSL2. The root issue was that, while sysctl and Systemd/systemctl are two completely different things, as therealkenc (of the Microsoft WSL team) points out, something must read and process /etc/sysctl.conf. In most Linux distributions, that's Systemd or the SysVInit scripts.

WSL, at the time, did not support Systemd, so ... nothing read and acted 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 the latest versions of WSL have 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.


  • 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"
    
Imprisonment answered 23/9, 2021 at 5:55 Comment(15)
Definitly the Dr01d I was lookin' for^^ Thank you a whole lot for your dedicated answer.Acetylide
The suggested feature request is underway in form of a pull request to their feature_request.md which I have accordingly changed. Though, I am not 100 % sure, this is the way they want to receive their feature requests. Anyhow, I went with your last approach, before testing what adding sysctl -w vm.max_map_count=262144 as a line directly in etc/profile under wsl -d docker-desktop could do, expecting it to be read on docker-desktop startup before any container is started, as docker-desktop itself is listed as a distro under wsl --list.Acetylide
Hence, I considered that whenever Docker-Desktop is started, it might read /etc/profile of this distro going by the same name. Thereagainst, /etc/profile appears not to be read when starting docker-desktop. Notably, it is read and effectively changes mmap-count when starting wsl -d docker-desktop similar to the result of your last approach when starting the seperate WSL (e. g. openSUSE Leap 15.2^^). Isn't it the way, that docker-desktop itself starts the wsl distro docker-desktop and hence should just as well read this profile and set the mmap-count defined within it?Acetylide
@Acetylide Not necessarily. Docker Desktop is likely starting up as a non-interactive, non-login shell, perhaps not intentionally, but because they pass commands to it through wsl when they start it up. For instance, if you do wsl -e bash -c "echo 1", the 1 will be output, but it will not read /etc/profile because it is not a login shell.Imprisonment
Thank you @NotTheDr01ds. In your answer, can you please add a statement on if or if not sysctl parameters can be defined in .wslconfig?Acetylide
@Acetylide You know, I totally forgot to follow up on the .wslconfig part of it in the whole sysctl rabbit-trail. And it turns out it was not easy to find the answer. But good news -- It's possible via .wslconfig. I'm about to start working on editing the answer to include that as the primary solution.Imprisonment
so glad you followed the rabbit/me all the way until closing my escape circle returning to where it started^^ Interestingly, the webpage Docker-Desktop for Windows links to under Settings>>Ressources>>Advanced learn.microsoft.com/en-us/windows/wsl/… apparently not older than just from yesterday, states "Global configuration options with .wslconfig in only available for distributions running as WSL 2 in Windows Build 19041 and later."Acetylide
Running on Build 18363, .wslconfig is probably not an option for me, albeit not stubbornly tested yet. I will do this, and, in addition, I will test if this distro-specific wsl.conf described on that same page can serve as an alternative when changed in accordance with the syntax you suggest in your answer for the .wslconf.Acetylide
In addendum to my prior comment on testing to add sysctl -w vm.max_map_count=262144 as a line in /etc/profile under wsl -d docker-desktop, this line is not contained in this file anymore. It persisted a couple of reboots before. At the moment, to me, the reason for this line missing remains obscure.Acetylide
Defining mmap count in .wslconfig to persist the reboot in accordance with the accepted answer by @Imprisonment also worked in Windows Build 18363Acetylide
@Acetylide I was thinking it was going to. The upgraded kernel is available in prior Windows releases, assuming that you have "Receive updates for other Windows products when you update Windows" on in Windows Update (and it's the default setting). I just have it turned off on most of my systems, so I was on the older kernel. The big change in 19043 is that you can run wsl --upgrade to get the kernel update even if the Windows Update doesn't do it.Imprisonment
@Acetylide Ah, but I didn't realize the doc said .wslconfig was that recent. Good to hear that still worked, though.Imprisonment
@Acetylide Regarding the profile being reset in docker-desktop, also not surprising to me. I get the feeling that that instance is supposed to be somewhat of a "black box" to users. It's infrastructure for the Docker Desktop WSL2 integration, and we (as users) probably aren't supposed to be mucking with it. That said, it (usually) never hurts to try :-).Imprisonment
Yes, I precautiously articulated my test result, not to oppose it completely against this statement regarding the minimum Windows build in the doc under link provided in my comment. I have the impression that .wslconfig is older than build 19041 as apparently is this kernelCommandLine-key in it. But maybe, they refer to at least one other .wslconfig-key which will not be functional in an older build.Acetylide
wish I could upvote this multiple times; such an amazingly researched answer.... :pray:Detritus
S
2

I have Windows 10 with Docker Desktop and Git installed. Following the instructions provided by @NotTheDr01ds, I opened a Git bash console with:

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

After that change, SonarQube's ElasticSearch started with no error.

Swain answered 9/8, 2022 at 8:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.