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

这几天思考了一下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. meglinge
    10 月前
    2024-1-30 15:42:32

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

    • meglinge
      meglinge
      10 月前
      2024-1-30 16:31:53

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

      • 博主
        meglinge
        10 月前
        2024-1-31 17:00:07

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

  2. baron
    8 月前
    2024-4-12 13:38:58

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

    • 博主
      baron
      8 月前
      2024-4-13 2:17:51

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

发送评论 编辑评论


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