WSL2 Arch+Docker个人配置过程和踩坑记录,以及一些建议
本文最后更新于 335 天前,其中的信息可能已经有所发展或是发生改变。

这几天思考了一下 Windows 下个人对于虚拟化的要求,以及虚拟机的实际使用情况,发现 Windows 下除了 Linux 开发环境用 VM 开的非常多,平常很少使用到 VM。而且目前已经几乎不会使用 VMware Workstation 单独开一个带桌面环境的 Linux VM。

然后,突然发现目前自己的需求挺适合使用 WSL 的。所以就花了点时间配置了一下 WSL 2,相比之前版本的 WSL 2,目前的版本用起来确实不错。

本文发布时,正式版 WSL 版本为 2.0.9。

先简单的介绍一下 WSL

WSL,全称为 Windows Subsystem for Linux,是一个在 Windows 环境下执行 Linux 程序的兼容层。WSL 的首个版本最早发布于 2016 年 8 月。

早期的 WSL1 是真正意义上的兼容层。对,就是在 Windows 内核里实现 Linux 系统调用。由于种种原因和困难,WSL1 最后停止了开发。

2019 年 5 月,WSL2 发布。WSL2 实际上来说是一个轻量的 Hyper-V 虚拟机,然后这个虚拟机通过容器技术来运行多种多样的发行版。在虚拟机里直接运行 Linux 的难度,相比在 Windows 内核内实现 Linux 系统调用,要简单的多。

WSL2 经过数年的发展,现在可以直接在 WSL 内运行 GUI 程序,使用主机的 GPU 加速。后来 WSL2 加入了 CUDA 支持,现在在 WSL2 内可以直接使用 CUDA 跑深度学习等需要 CUDA 的东西,效率比在 Windows 上跑要快很多(不过达不到直接在 Linux 上跑的效率,虚拟机肯定会有损耗)。

wsl2

你是否适合使用 WSL2?

如果你是想完整的学习 Linux,那我还是建议你使用虚拟机软件装一个比较容易入门的 Linux 发行版,以避免撞 WSL 独有的一些坑。WSL2 我只推荐已经熟悉 Linux,然后需要一个方便的开发环境的读者使用。

因为 WSL2 使用了 Hyper-V 技术,因此依赖虚拟机的用户,或对 Hyper-V 反感的用户,请慎重考虑。

简单来说就是下面四点:

  • 如果你能完善的解决 Hyper-V 的问题,就可以上 WSL2。
  • 当前 VMware Workstation 和 Oracle VM VirtualBox 最新版本可以和 Hyper-V 共存,但是可能有小问题,得看你能不能接受。
  • 手游模拟器用户请确认你目前使用的模拟器是否支持和 Hyper-V 共存。
  • 如果你使用的某些其他软件也需要虚拟化技术,请确认这些软件是否可以和 Hyper-V 共存。

另外个人觉得 WSL2 是专门设计给开发者使用的,所以开发环境下用用还是不错的。不是很推荐在生产环境下使用?(哎呀都生产环境了你咋不直接上 Linux 实体机系统呢)

以下是一些补充说明,可以不看。

目前有 Windows Hypervisor Platform(下文简称 WHP),情况已经比当年好一些了,但是,也不是所有软件都适配了这玩意。

目前 Windows 下常用的两个桌面级 Type-2 Hypervisor(VMware Workstation 和 Oracle VM VirtualBox)的最新版已经支持 WHP,也就是已经可以和 Hyper-V 共存,不过可能会产生一些小问题,得看你能不能接受:

  • VMware Workstation 和 VirtualBox 与 Hyper-V 共存时会失去嵌套虚拟化能力,不过正常情况下应该没人玩虚拟机套娃吧。
  • VMware Workstation:目前运行绝大多数最新版操作系统应该没有什么太大问题。运行部分早期的操作系统(比如 Windows 2000)可能会出现性能下降。另外 VMware Workstation 16.2 及之后的版本,Linux VM 可能出现键盘输入卡顿的情况(目前确定是 VMware Workstation 的锅,看什么时候修复了)。
  • VirtualBox:略微的性能下降,但是用着没有太大问题。

市面上大部分模拟器都基于 VirtualBox,不过即便如此,目前很多手游模拟器依然还不支持 Hyper-V,建议事先确认你使用的手游模拟器是否支持 Hyper-V。

UPDATE on Jan 18, 2024:博主目前试了下 Bluestacks 5 国际版最新版本,可完美兼容 Hyper-V,且性能还不错。

bs5-with-wsl

至于我,我直接把用了多年的 VMware Workstation 扬了,换成 Hyper-V,毕竟我感觉我自己跑虚拟机很少用 3D 加速。

安装 WSL2

在 “启用或关闭 Windows 功能(Turn Windows features on or off)” 界面,打开 “虚拟机平台(Virtual Machine Platform)” 和 “Windows 虚拟机监控程序平台(Windows Hypervisor Platform)”。打开这两个功能应该会提示需要重启一次。

enable-virt-platform-cn

在重启完成后,前往 Microsoft Store 下载 WSL2。下载完成后你就拥有了 WSL2 本体了,不过,你还得装一个发行版,才能开始使用 WSL2。

wsl2-in-msstore

Microsoft Store 里已经有相当多的 WSL2 发行版了,如果你在这里找到了你想用的发行版,直接在这里安装就可以了。

wsl2-distros

当然,你也可以自己构建一个发行版的文件系统,并提供给 WSL2 使用。下面我们即将在 WSL2 里安装 Arch Linux,就需要这么做。

向 WSL 安装 Arch Linux

警告
Arch Linux on WSL 并不受到 Arch Linux 官方支持(但是不代表不能用)。因此当你在 WSL2 中使用 Arch Linux 时出现了问题,向 Arch Linux 官方反馈 bug 之前,请确保该问题能在受支持的 Arch Linux 环境(如直接实体机或虚拟机运行的环境)下复现。

除了直接安装商店里的 WSL 发行版之外,你还可以自行制作你想用的 Linux 发行版的 rootfs,打包成 tar.gz 格式,然后手动导入 WSL。

# 导入发行版
wsl --import <DistroName> <InstallLocation> <InstallTarFile>
# 设置默认启动的发行版
wsl -s <Distro>

现成的 rootfs

目前已经有开发者制作了现成的 Arch Linux rootfs,如果你不想手动制作 rootfs,或者是为了方便,可以直接使用,不过在使用时记得阅读相关的说明。

这里推荐使用 yuk7 的 ArchWSL:GitHub。该 rootfs 可同时用于 WSL1 和 WSL2。

另外我个人也同时制作了一个专门针对 WSL2,定时更新最新版的 rootfs,也可以看一下:GitHub

另外,不管用的是谁的 rootfs,在配置完成后记得及时更新系统(pacman -Syu)。

制作一个 rootfs

你首先需要有一个现成的 Arch Linux 环境。

当然,你可以使用别的发行版,如果你打算如此,请确保你所使用的发行版下,Arch Linux 的包管理 pacman 可以正常工作。

下面的制作 rootfs 命令仅供参考。

pacman -S arch-install-scripts
# /tmp/rootfs-skeletion 和 /tmp/rootfs 可以换成你喜欢的路径
sudo mkdir /tmp/rootfs-skeletion
# 这里需要保证/tmp/rootfs是挂载点,防止后面配置出问题
sudo mount --mkdir --bind /tmp/rootfs-skeletion /tmp/rootfs
# 接下来两步你应该比较熟悉
# 请根据你的实际需要更改pacstrap步骤安装的包
pacstrap -K /tmp/rootfs base curl wget vim sudo texinfo man-db man-pages
arch-chroot /tmp/rootfs
# 接下来按照你喜欢的方式配置rootfs
# 清理包换成以缩减rootfs.tar.gz的体积
rm -rf /tmp/rootfs/var/cache/pacman/pkg/*
# 打包rootfs.tar.gz
tar -czf ~/rootfs.tar.gz -C /tmp/rootfs ./
# 清理工作
sudo umount /tmp/rootfs
sudo rmdir /tmp/rootfs
sudo rm -rf /tmp/rootfs-skeletion

将 rootfs.tar.gz 复制到 Windows,然后将其导入 WSL 即可使用。

若在之前的步骤中没有配置非 root 账号和 sudo,在正式使用前,建议先创建一个非 root 账号并配置好 sudo。

同时在正式使用之前,建议关闭 WSL 自动追加 Windows PATH 环境变量的设置。

pacman -S sudo
echo '%wheel ALL=(ALL:ALL) ALL' > /etc/sudoers.d/wheel
useradd -m -G wheel azurezeng
passwd azurezeng
cat << EOF > /etc/wsl.conf
[interop]
appendWindowsPath=false
[user]
default=azurezeng
EOF

这样我们就得到了 Arch Linux on WSL。(下图的 WSL Linux 内核版本由我本人进行编译,因此与 WSL 自带的 Linux 内核版本不一致)

arch-on-wsl

使用 Docker Desktop

直接去 Docker Desktop 官网下载,非常简单。

docker-desktop-site

软件授权提醒
Docker Desktop 对于个人使用和初创企业(员工数少于 250 位并且年收入少于 10,000,000$)免费授权,否则需要购买付费订阅。
不过这个是大企业需要考虑的事情的,个人使用没啥顾虑。

在安装完成后,除了在 Windows 上直接调用 docker,Docker Desktop 会自动与默认的 WSL 发行版集成,可以手动设置 Docker Desktop 和哪些 WSL 发行版集成。

docker-desktop-main-window

docker-desktop-integration-with-wsl

一些个人遇到的坑

systemd

有的时候可能需要使用到 systemd 的服务管理功能。在 /etc/wsl.conf 中设置相关选项以启用 systemd 支持。

[boot]
systemd=true

同时建议关闭 systemd-journald 的日志持久化功能(就是让 journald 的日志只保存在内存中),以节约硬盘空间。

# /etc/systemd/journald.conf.d/wsl.conf
[Journal]
Storage=volatile
RuntimeMaxUse=200M

WSLg

首先我遇到的第一个问题是,WSL 启动时会调用 NVIDIA 独立显卡,会导致笔记本发热量上升。之前尝试了各种方法都没有完美的解决这个问题。最近发现在.wslgconfig 里指定环境变量 MESA_D3D12_DEFAULT_ADAPTER_NAME=Intel(我是 Intel 集成显卡用户)可以让 WSLg 的相关进程优先调用集成显卡,问题完美解决,不过我的办法在 WSLg 官方的文档里没有详细说明。

以及我不是很想 WSL 内的安装的程序在开始菜单中出现,这个官方给了相关设置。

至于分数缩放,只能说无解咯,目前(2023 年末左右)原生 Linux 桌面环境普遍对分数缩放不好。

关于 WSLg 配置文件 ~/.wslgconfig 里设置选项,可以参考官方的相关文档。这里也放出自己的.wslgconfig 以供各位参考。

[system-distro-env]
WESTON_RDP_APPLIST=false
; Suppress wakeup of NVIDIA discrete card
;LIBGL_ALWAYS_SOFTWARE=1
; Prefer using Intel integrated graphics card
MESA_D3D12_DEFAULT_ADAPTER_NAME=Intel

WSL 2.0.x 下内存回收和硬盘空闲空间回收

先前的 WSL 有着比较让人不舒适的内存泄露问题,目前在 ~/.wslconfig 内设置 autoMemoryReclaim=dropcache 可以解决问题(此选项在 2.1.3 版本之后为默认值)。

同时,可以设置 sparseVhd=true,之后新安装的发行版均会自动回收其虚拟硬盘文件的空闲空间。对于已经安装的发行版,可以使用 wsl --manage <Distro> --set-sparse <true/false> 为发行版的虚拟硬盘文件启用该功能。

[wsl2]
autoMemoryReclaim=dropcache # dropcache/gradual/disabled,设置成gradual则发行版内不建议打开systemd功能
[experimental]
sparseVhd=true

WSL 2.0.x 下的 mirrored 网络

mirrored 网络可让 WSL 的网络环境和主机环境一致(主机和 WSL 内的端口互通),并支持 IPv6。此功能对宿主机的要求为 Windows 11 22H2 Build 22621.2338+。

目前 Docker Desktop 已对 networkingMode=mirrored 提供较好支持。直接在发行版中运行的 Docker CE,需要在 /etc/docker/daemon.json 中设置 "iptables": false,虽然个人觉得这么做不是很优雅。

[experimental]
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
hostAddressLoopback=true

关于 WSL 的 NAT 网络下的宿主机 IP 固定

若因为部分特殊原因,不打算使用 mirrored 网络,或未对 WSL 网络相关选项进行配置,则默认使用 NAT 网络。

Linux 下,可以通过 ip addr 查看 WSL 的 IP 地址。Windows 下可以通过 ipconfig 查看 NAT 虚拟网卡的 IP 地址。

PS E:\Temp> wsl ip -color=auto addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 10.255.255.254/32 brd 10.255.255.254 scope global lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:15:5d:57:3d:49 brd ff:ff:ff:ff:ff:ff
inet 172.17.228.46/20 brd 172.17.239.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::215:5dff:fe57:3d49/64 scope link
valid_lft forever preferred_lft forever
PS E:\Temp> ipconfig | grep -A 7 WSL
Ethernet adapter vEthernet (WSL (Hyper-V firewall)):
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::f1a0:df8c:1ebd:968c%65
IPv4 Address. . . . . . . . . . . : 172.17.224.1
Subnet Mask . . . . . . . . . . . : 255.255.240.0
Default Gateway . . . . . . . . . :
PS E:\Temp>

之前 Windows 侧用于给 WSL 进行 NAT 网络的虚拟网卡,在每次重启后其 IP 都会变动,导致 WSL 内程序访问宿主机上的程序会非常的不舒服。虽然之前有相当多的解决方案,但是依然不是很完美的。

这个问题在某次 WSL 更新后得到了解决。现在宿主机的 IP 和 WSL 的 IP 都在注册表内,可以手动修改。

  • WSL 的 IP 地址:HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss\NatIpAddress
  • 宿主机中的 NAT 设置:HKLM\Software\Microsoft\Windows\CurrentVersion\Lxss\NatNetwork
  • 宿主机中的 NAT 虚拟网卡 IP 地址:HKLM\Software\Microsoft\Windows\CurrentVersion\Lxss\NatGatewayIpAddress

修改完以上注册表之后建议重启 Windows 以应用更改。

内核更换(仅建议专业用户考虑)

如果 WSL 自带的 Linux 内核版本无法满足你的需求,可以在.wslconfig 中编辑使用自定义内核。需要注意的是,如果你使用的内核不带 dxgkrnl 驱动,则会导致 WSL 的 GPU 加速失效。

如果发现 WSL 有一些问题,若设置了自定义内核则建议先禁用自定义内核再排错。

[wsl2]
kernel=E:/Virtual Machines/WSL/Kernels/linux-6.6.11-bzImage

这里附上目前我目前正在使用的最新 LTS 内核的 GitHub Repo:Nevuly/WSL2-Linux-Kernel-Rolling

一些杂项问题

部分情况下 WSL 发行版内的 ping 命令可能会需要 root 权限才能使用,否则报错。解决办法为修改 WSL 的内核命令行参数(kernelCommandLine),向 WSL 传入 net.ipv4.ping_group_range=\"0 2147483647\" 的 sysctl 选项来解决问题。

另外我偶尔可能也要设置 WSL 的内存使用上限(WSL 2.0.x 之前我一般设置 WSL 的内存上限为 8GB),这个可以透过 memory 选项达到。

[wsl2]
#memory=8GB
kernelCommandLine=sysctl.vm.overcommit_memory=1 sysctl.net.ipv4.ping_group_range=\"0 2147483647\"

评论

  1. m
    meglinge
    2024-1-30
    2024-1-30 15:42:32

    现在在 Arch 能调用 vulkan 程序吗,我尝试安装 arch 仓库里面的 mesa,是不行的只能调用 opengl。如果我手动编译安装 mesa 然后指定 vulkan-drivers=microsoft-experimental 后就可以运行 vulkan 程序,但是 opengl 的运行不了了。

    • m
      meglinge
      meglinge
      2024-1-30
      2024-1-30 16:31:53

      找到问题了 arch 官方包里面 vulkan-drivers 没有包含 microsoft-experimental, 而且 microsoft-clc 也是 disable 的,我在 aur 里面找到了 mesa-enable-h264 这个包,他 pkgbuild 把所有的特性都选成 All,换成这个了之后就可以用了。

      • A
        博主
        meglinge
        2024-1-31
        2024-1-31 17:00:07

        毕竟 arch in wsl 不受 arch 官方支持

  2. baron
    2024-4-12
    2024-4-12 13:38:58

    还是没法回收磁盘,我编一下 sdk 少 2g, 编着编着磁盘就没了 =-=, 以前可以
    mount /dev/sda -o remount,ro
    zerofree /dev/sda
    但是更新之后没法 mount 根目录了 =-=
    有办法手动回收磁盘嘛,研究了很久没找见方法.

    • 博主
      baron
      2024-4-12
      2024-4-13 2:17:51

      我这边 sparseVhd 是有效的,不是很清楚你那边什么情况,因为 WSL 的 sparse VHD,内部用的技术目前是不清楚的

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇