Repository navigation
Description
Bug report
Bug description
On the WSL2 backend, Docker Desktop's /initd writes VM-wide vm.* sysctls into the kernel every WSL2 distro shares — turning off proactive compaction and watermark boosting for all of them, and overwriting the distros' own sysctl settings.
All WSL2 distros run in one utility VM with one kernel, and vm.* sysctls are not namespaced. When the
docker-desktop distro starts, its init daemon applies a kernel-tuning table to that shared kernel. Two of
its entries, vm.compaction_proactiveness=0 and vm.watermark_boost_factor=0, disable both of the
kernel's background defences against memory fragmentation for every distro on the machine. Others lower or
override values a distro sets itself (Ubuntu's vm.max_map_count=1048576 becomes 262144). Because /initd
runs after the distro's systemd-sysctl, a user's /etc/sysctl.d loses.
Consequence. With both mechanisms off, physically contiguous high-order allocations fail under ordinary page-cache
load even with plenty of free memory. WSL's own host-to-guest hv_sock connections each need one 512 KiB
contiguous block (microsoft/WSL#40795), so on this machine:
- 0.91% of host-to-guest channel opens failed over a 46-minute measured window (49 of 5395);
- Windows
.exeinterop calls from WSL failed with exit 1 after 10 s (UtilAcceptVsock:281: accept4 failed 110); wsl.exesessions failed after 30 s;- 29–276 printed order-7 allocation failures per boot across seven boots.
At the failure points the Normal zone often had hundreds of MiB (once 11 GB) free with no block of order 7
or larger, and every failure report shows boost:0kB: the kernel's response to fragmentation events is
switched off.
In 2019 Docker declined to set shared sysctls on this backend for exactly this reason — "as modifying this
sysctl setting would apply to all wsl distros (they all run in the same VM), we won't do that
automatically" (#5202 comment).
A 2024 comment on #5202 reports
max_map_count being overwritten to 262144 against the user's own setting. No existing issue covers the
compaction or watermark-boost settings.
Reproduction steps
Docker Desktop 4.97.0 (244584), WSL 3.0.3.0, kernel 6.18.54.1-microsoft-standard-WSL2, Windows 11,
Ubuntu-24.04 distro. With Docker Desktop running, in the Ubuntu distro:
$ sysctl vm.compaction_proactiveness vm.watermark_boost_factor vm.max_map_count vm.overcommit_memory vm.page-cluster vm.stat_interval vm.dirty_writeback_centisecs kernel.keys.maxkeys
vm.compaction_proactiveness = 0
vm.watermark_boost_factor = 0
vm.max_map_count = 262144
vm.overcommit_memory = 1
vm.page-cluster = 2
vm.stat_interval = 30
vm.dirty_writeback_centisecs = 1500
kernel.keys.maxkeys = 10000
$ grep -v '^#' /etc/sysctl.d/10-map-count.conf
vm.max_map_count=1048576
Ordering on the same boot (journalctl -b -u systemd-sysctl and journalctl -k):
15:44:50 systemd[1]: Finished systemd-sysctl.service - Apply Kernel Variables.
15:48:17 WSL (1 - init(docker-desktop)) ...
15:48:20 kernel: netlink: 'initd': attribute type 4 has an invalid length.
Every value above matches /initd's table, not the kernel default or the distro's setting (kernel
defaults from source: compaction_proactiveness 20, watermark_boost_factor 15000, page-cluster 3,
stat_interval 1, dirty_writeback_centisecs 500, overcommit_memory 0, keys.maxkeys 200). I have not
captured the same distro's values with Docker Desktop fully stopped on a fresh VM; that is the expected
control. kernel.pid_max, also in the table, is not overridden in Ubuntu because it is per-pid-namespace
on 6.18, which fits the per-key reading below.
Where it comes from (shipped binary)
In the shipped docker-desktop.iso:/initd (4.97.0, Go 1.27.3, sha256
37ddac517530bcdf87c40c2b1df37188d093a6ee6204df43e64edbfba3c27b43), the string
/proc/sys/vm/compaction_proactiveness occurs once. The Go line table places its only reference in
github.com/docker/pinata/linuxkit/pkg/initd/sysctl.OtherKernelConfig (sysctl/sysctl.go:49), applied by
initd.(*baseServices).startSysctl.func1 (initd/sysctl.go:28–29) → initd.writeFile → os.WriteFile,
once per start. The same table holds watermark_boost_factor, max_map_count, overcommit_memory,
page-cluster, stat_interval, dirty_writeback_centisecs, the hung-task settings and the kernel.keys
limits.
Fix sketch
On the WSL2 backend, where the kernel is shared:
- Don't write keys that lower or disable kernel defaults — at minimum
vm.compaction_proactivenessand
vm.watermark_boost_factor, which only affect background memory management. - For keys Docker needs at a minimum (
vm.max_map_count), raise only: write the value only when the
current one is lower. - Or make the table opt-out, so a user who tunes their own distro can keep it.
Workaround for affected users: re-apply the distro's /etc/sysctl.d on a timer after Docker starts
(e.g. a systemd timer running systemd-sysctl every few minutes). Each Docker start still resets the
values until the next run.
Platform
Windows
Version information
Client:
Version: 29.9.2
API version: 1.56
OS/Arch: linux/amd64
Context: default
Server: Docker Desktop 4.97.0 (244584)
Engine:
Version: 29.9.2
API version: 1.56 (minimum version 1.40)
OS/Arch: linux/amd64
containerd:
Version: v2.4.2
runc:
Version: 1.5.2
docker-init:
Version: 0.19.0
WSL 3.0.3.0, kernel 6.18.54.1-microsoft-standard-WSL2, Windows 11, WSL2 backend, Ubuntu-24.04 distro alongside docker-desktop
Activity
bsousaa commentedon Nov 2, 2026
@0xdhx please include a diagnostics id in your issue report
0xdhx commentedon Nov 4, 2026
@bsousaa Diagnostics ID:
01EFED8D-7EBF-4EAA-BB3D-167A7612FBC3/20261104061439, uploaded 2026-11-04 from Docker Desktop 4.98.0 (245422).It still reproduces on 4.98.0. The bundle's
sysctl -aran 31 s after adocker desktop restart, while Docker's values were still in effect. The bundle'svm/system/sysctl.txtshows:That file is the
docker-desktopdistro's view. The kernel is shared, so the Ubuntu-24.04 distro saw the same values at the same moment. Sampled from Ubuntu every 0.5 s across the restart:An earlier restart the same night, at 00:09:53, did the same: the values were zeroed at 00:10:07.4. The 4.98.0
docker-desktop.iso:/initd(sha256e66b720f3fda07546fd7b47099658db874a052ea8071c87e6e92e39d58db05a0) still contains thesysctl.OtherKernelConfigsymbol and the/proc/syspaths forcompaction_proactiveness,watermark_boost_factor,max_map_count,overcommit_memory,page-cluster,stat_interval,dirty_writeback_centisecsandkeys/maxkeys.