WSL2 Ubuntu 21.04原生Docker无法运行的问题
最近为了用上更新一点的软件,把运行在WSL2里的Ubuntu 20.04 LTS版本升级了一下,升级到了Ubuntu 21.04,升级之后呢,大部分功能都正常(当然本身我用的功能也不会很多),但是确实也遇到了个小问题:Docker Daemon无法启动了。这个确实很影响工作,因为很多时候写完代码会本地打个镜像运行一下,简单测试一下代码是否有问题。但是升级之后,突然发现Docker用不了了。
具体点呢,是会报一个iptables
相关的错误:
......
WARN[2021-10-23T11:30:05.864210900+08:00] Your kernel does not support cgroup blkio throttle.write_iops_device
INFO[2021-10-23T11:30:05.864538700+08:00] Loading containers: start.
INFO[2021-10-23T11:30:06.135353300+08:00] stopping event stream following graceful shutdown error="context canceled" module=libcontainerd namespace=moby
INFO[2021-10-23T11:30:06.135542600+08:00] stopping healthcheck following graceful shutdown module=libcontainerd
INFO[2021-10-23T11:30:06.136083800+08:00] stopping event stream following graceful shutdown error="context canceled" module=libcontainerd namespace=plugins.moby
failed to start daemon: Error initializing network controller: error obtaining controller instance: unable to add return rule in DOCKER-ISOLATION-STAGE-1 chain: (iptables failed: iptables --wait -A DOCKER-ISOLATION-STAGE-1 -j RETURN: iptables v1.8.7 (nf_tables): RULE_APPEND failed (No such file or directory): rule in chain DOCKER-ISOLATION-STAGE-1
(exit status 4))
提示iptables
RULE_APPEND
也不知道是咋回事,不过想着估计和Docker的网络有点关系,还好一般情况下编译和打镜像也不需要网络隔离,所以前几天就临时在启动Docker Daemon时加上--iptables=false
参数,不加载iptables规则,当然docker builld
和docker run
的时候也得加上--network=host
使用不隔离的Host网络,勉强扛了几天。
今天有时间就查了查资料,一开始查到的大部分都是让用Docker Desktop for Windows
并且开启WSL2后端,然后在WSL2里直接用Windows的docker.exe
命令。这个方案我没试过,不过说实话即使能用,也觉得有点太别扭了。想想还是放弃了。于是继续找资料。终于找到一篇文章,文章里贴了个Ubuntu的bug report,大致意思是说:
Ubuntu从20.10开始,将默认的防火墙切换到了
nftables
实现,这个实现需要5.8版本及以上的内核,而微软在WSL2中提供的5.4版本的内核没有nftables
,所以导致iptables功能出错了。
解决方法也简单,直接把iptables
实现切换回iptables-legacy
就好了:
~]# sudo update-alternatives --config iptables
There are 2 choices for the alternative iptables (providing /usr/sbin/iptables).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/sbin/iptables-nft 20 auto mode
1 /usr/sbin/iptables-legacy 10 manual mode
2 /usr/sbin/iptables-nft 20 manual mode
Press <enter> to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode
切换回去之后,果然就好了,又可以开心的用原生docker了。
最后我又看了眼现在跑的内核:
~]# uname -r
5.10.60.1-microsoft-standard-WSL2
因为升级了Windows11,现在内核已经到了5.10了。按理不应该有问题才对。除非微软编译内核的时候没开相关的选项?
~]# zcat /proc/config.gz |grep NF_TABLES
CONFIG_NF_TABLES=y
CONFIG_NF_TABLES_INET=y
# CONFIG_NF_TABLES_NETDEV is not set
CONFIG_NF_TABLES_IPV4=y
# CONFIG_NF_TABLES_ARP is not set
CONFIG_NF_TABLES_IPV6=y
# CONFIG_NF_TABLES_BRIDGE is not set
确实有些选项没打开,而且WSL的github issue里似乎也有类似的讨论:#6655、#6044、#4165。不过微软似乎也没想着解决,不过问题不大啦,也没到要自己编译内核的地步。能用就行~