使用 Docker-Desktop for Windows,如何配置 sysctl 参数以渗透重新启动?

Posted

技术标签:

【中文标题】使用 Docker-Desktop for Windows,如何配置 sysctl 参数以渗透重新启动?【英文标题】:Using Docker-Desktop for Windows, how can sysctl parameters be configured to permeate a reboot? 【发布时间】:2021-11-11 19:02:23 【问题描述】:

在 win10 [wsl2] docker-desktop 中运行 elasticsearch 需要通过 sysctl -w vm.max_map_count=262144 将 mmap 计数增加到 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

在an answer to this question 和elastic's doc 中建议相应地更新/etc/sysctl.conf 中的vm.max_map_count 以将此值设置为永久,即。 e.使其在重新启动后仍然存在。

请注意下面的输出,显示有效 mmap 计数不适应 sysctl.conf 中定义的值,在我尝试遵循此建议并重新启动后。

为什么没有?

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

考虑到在etc/ 中更改了错误的sysctl.conf,我尝试更改&lt;hostname&gt;:/tmp/docker-desktop-root/etc# 中的sysctl.conf。 这是不允许的,因为这是Read-only file system

是否可以/应该在 .wslconfig 中对其进行参数化,如果可以,如何?

使用 openSUSE Leap 15.2 代替 Win10 的 PowerShell 并没有改变结果。

<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

值得注意的是,上述 sysctl.conf 文件中的标头引用了 /boot/sysctl.conf-&lt;kernelversion&gt;。考虑到可能需要在此文件中定义 mmap 计数以便在启动时考虑,我尝试在那里设置所需的参数,但无权这样做。

<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

openSUSE:WSL - openSUSE Wiki 中报告的已知问题和限制之一是

WSL 中的系统实际上并没有引导并且不使用 systemd。专有的 Microsoft /init 二进制文件初始化系统。因此服务管理不像在虚拟机中那样工作。它的行为更像是一个交互式容器。

任何人都可以验证这是为什么参数化 sysctl.conf 不能成为实现手头目的的有效方法的原因吗?

系统

主持人 操作系统:Microsoft Windows 10 企业版 版本:10.0.18363 Build 18363 \

码头工人 客户: 版本:20.10.8 API 版本:1.41 Go 版本:go1.16.6 Git 提交:3967b7d 建成:2021 年 7 月 30 日星期五 19:54:02 操作系统/架构:linux/amd64 插件: 撰写:Docker Compose(Docker Inc.,v2.0.0-rc.2) 扫描:Docker 扫描(Docker Inc.,v0.8.0)

服务器: 引擎: 版本:20.10.8 API 版本:1.41(最低版本 1.12) Go 版本:go1.16.6 Git 提交:75249d8 建成时间:2021 年 7 月 30 日星期五 19:52:10 操作系统/架构:linux/amd64 容器化: 版本:1.4.9 GitCommit:e25210fe30a0a703442421b0f60afac609f950a3 运行: 版本:1.0.1 GitCommit:v1.0.1-0-g4144b63 码头工人初始化: 版本:0.19.0 GitCommit: de40ad0 \

内核版本:5.10.16.3-microsoft-standard-WSL2 操作系统:Docker 桌面 操作系统类型:linux 架构:x86_64 CPU:4 总内存:12.39GiB 名称:码头工人桌面

【问题讨论】:

【参考方案1】:

简答:

在您的 Windows %userprofile% 目录(通常为 C:\Users\&lt;username&gt;)中,使用以下内容创建或编辑文件 .wslconfig

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

然后退出任何 WSL 实例 wsl --shutdown,然后重新启动。

> sysctl vm.max_map_count
vm.max_map_count = 262144

更多细节:

您确实有三个(密切相关的)问题:

(主要)如何最好地保留此设置 可以通过.wslconfig 完成吗?

是否可以/应该在 .wslconfig 中对其进行参数化,如果可以,如何实现?

为什么/etc/sysctl.conf 不努力坚持下去?

/etc/sysctl.conf 将此值设置为永久,即。 e.让它在重启后幸存下来......为什么没有呢?

我们将结合前两者,因为答案是“是的,您可以通过 .wslconfig 来完成。

这并不容易找到,因为更改是最近才发生的。它来了this answer。

从内核版本 5.8 开始,您可以在内核命令行上使用 sysctl.* 前缀设置 sysctl 值。

只要您升级了 WSL 内核(自从 wsl --update 最近在 21H1 发布以来,我的两个系统上没有没有),您可以将您的 %userprofile%\.wslconfig 设置为以上。


/etc/sysctl.conf

/etc/sysctl.conf 将此值设置为永久,即。 e.让它在重启后幸存下来......为什么没有呢?

自从我先走下这条兔子小道并将其作为原始答案发布以来,本节的内容比真正需要的要多得多。但首先,“为什么”它不起作用......

这是带有 WSL2 的 known issue。

虽然sysctl 和 Systemd/systemctl 是两个完全不同的东西,但在那个问题中,therealkenc(Microsoft WSL 团队的)指出 something 必须读取和处理 /etc/sysctl.conf。在大多数 Linux 发行版中,这是 Systemd 或 SysVInit 脚本。

另一方面,WSL 使用它自己的 /init 代替 SysVInit 或 Systemd。 WSL init 进程(当前)没有在启动时运行服务的机制,正如您在 openSUSE 文档中找到的那样。所以......在启动时没有任何内容读取和操作/etc/sysctl.conf


这个答案的其余部分包括一些不需要的systcl.conf 解决方法,因为我们可以使用.wslconfig 来做到这一点。这是为了以防万一有人因为某种原因发现它有用。

有一些解决方法。所有这些都将涉及找到一种自动运行sysctl -w vm.max_map_count=262144(作为root)的方法:

首先,在 Windows 11 中,WSL 有一个新功能可以简化这一点。只需使用以下命令创建/编辑/etc/wsl.conf(通过sudo):

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

这将在每次 WSL 实例启动时在根目录下运行。据我所知,这也可以在 docker-desktop 实例中工作,但我无法对其进行测试。

重要提示:在尝试此更改之前,请使用 wsl --export 备份您的 WSL 实例,或至少备份您的 Docker 卷、映像和容器。根据我的经验,可以通过停止的启动命令完全阻止实例启动,而我(还)没有找到恢复机制。幸运的是,我在一个新安装的测试实例中工作,所以我能够wsl --unregister它(完全摧毁它)而不会丢失任何东西,除了几分钟。


对于我们中的许多将在未来一段时间内使用 Windows 10 的人来说,有多种选择。不幸的是,我无法针对 Docker 测试这些,但我过去曾在其他 WSL 实例中使用过类似的技术:

如果 Docker Desktop 设置为在您登录时运行,那么您可以添加一个计划任务(通过 Windows 任务计划程序)以在登录时也运行。这将是:

“基本任务” “程序”设置为wsl.exe 参数设置为-d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"

请注意,如果 docker-desktop WSL 实例在任何时候终止,则更改将丢失,直到下次重新启动。但是,由于 Docker Desktop 在启动/登录时运行,因此实例应该保持这种变化。


根据您的工作流程,这可能适合也可能不适合。如果您将单独的 WSL 实例(例如 Ubuntu)用于开发目的,您可以在启动时让 那个 实例修改 docker-desktop 实例。

这样您就不必每次启动时都输入sudo 密码, 在您的.bashrc(或等效项)中使用以下行:

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

最后一个建议——向 Docker Desktop 团队提交功能请求。恕我直言,Docker Desktop 的启动过程最容易读取/etc/sysctl.conf 并进行相应的处理。

【讨论】:

绝对是我一直在寻找的 Dr01d^^ 非常感谢您的热心回答。 建议的功能请求正在以对他们的 feature_request.md 的拉取请求的形式进行,我已相应地进行了更改。虽然,我不能 100% 确定,但这是他们希望接收功能请求的方式。无论如何,在测试直接在etc/profile 下的wsl -d docker-desktop 下添加sysctl -w vm.max_map_count=262144 作为一行之前,我采用了你的最后一种方法,希望在启动任何容器之前在 docker-desktop 启动时读取它,因为 docker- desktop 本身在 wsl --list 下被列为发行版。 因此,我认为每当启动 Docker-Desktop 时,它可能会读取此发行版的/etc/profile 同名发行版。相反,/etc/profile 在启动 docker-desktop 时似乎不会被读取。值得注意的是,它在启动 wsl -d docker-desktop 时被读取并有效地更改 mmap-count,类似于您在启动单独的 WSL(例如 openSUSE Leap 15.2^^)时的最后一种方法的结果。不是这样吗,docker-desktop 本身会启动 wsl 发行版 docker-desktop,因此也应该阅读此配置文件并设置其中定义的 mmap-count? @ToOolzZz 不一定。 Docker Desktop 很可能作为非交互式、非登录 shell 启动,这可能不是故意的,而是因为它们在启动时通过 wsl 向它传递命令。例如,如果您执行wsl -e bash -c "echo 1",则会输出1,但不会读取/etc/profile,因为它不是登录shell。 是的,我谨慎地阐明了我的测试结果,而不是完全反对我评论中提供的链接下的文档中关于最低 Windows 构建的声明。我的印象是 .wslconfig 比 build 19041 更早,因为其中的 kernelCommandLine-key 显然是这样的。但也许,它们至少引用了一个其他 .wslconfig-key,这在旧版本中将不起作用。

以上是关于使用 Docker-Desktop for Windows,如何配置 sysctl 参数以渗透重新启动?的主要内容,如果未能解决你的问题,请参考以下文章

Docker-desktop(Docker桌面版)——入门篇

Docker-Desktop储存路径更改

WSL2修改存储位置(示例:Docker-Desktop)

基于WSL2 的 Docker Desktop 启动时 Failed to set version to docker-desktop exit code -1的解决方法

windows 10安装docker

Docker for windows 或者 docker-ce 加速下载镜像配置