Docker in WSL2

在Windows上安装好wsl2后使用docker可能出现如下问题:

➜  ~ sudo service docker start
Starting Docker: docker.
➜  ~ sudo service docker status
Docker is not running ... failed!

下面我们来分析并解决这个问题。

docker的log存储在/var/log/docker.log这个文件中。

可以使用grep命令来从log中提取关键错误信息。

grep error docker.log

在我的log中可以大概看到如下信息。

time="2020-05-30T11:04:14.475594100+08:00" level=warning msg="could not use snapshotter btrfs in metadata plugin" error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.btrfs must be a btrfs filesystem to be used with the btrfs snapshotter"
time="2020-05-30T11:04:14.475613300+08:00" level=warning msg="could not use snapshotter aufs in metadata plugin" error="modprobe aufs failed: "modprobe: FATAL: Module aufs not found in directory /lib/modules/4.19.104-microsoft-standard\n": exit status 1"
time="2020-05-30T11:04:14.475623000+08:00" level=warning msg="could not use snapshotter zfs in metadata plugin" error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.zfs must be a zfs filesystem to be used with the zfs snapshotter: skip plugin"
time="2020-05-30T11:04:14.504969300+08:00" level=warning msg="Running iptables --wait -t nat -L -n failed with message: `# Warning: iptables-legacy tables present, use iptables-legacy to see them\niptables v1.8.4 (nf_tables):  CHAIN_ADD failed (No such file or directory): chain PREROUTING\nChain PREROUTING (policy ACCEPT)\ntarget     prot opt source               destination         \n\nChain INPUT (policy ACCEPT)\ntarget     prot opt source               destination         \n\nChain POSTROUTING (policy ACCEPT)\ntarget     prot opt source               destination         \n\nChain OUTPUT (policy ACCEPT)\ntarget     prot opt source               destination`, error: exit status 4"
time="2020-05-30T11:04:14.528689400+08:00" level=info msg="stopping event stream following graceful shutdown" error="<nil>" module=libcontainerd namespace=moby
time="2020-05-30T11:04:14.529148600+08:00" level=info msg="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: failed to create NAT chain DOCKER: iptables failed: iptables --wait -t nat -N DOCKER: iptables v1.8.4 (nf_tables):  CHAIN_ADD failed (No such file or directory): chain PREROUTING
time="2020-05-30T11:04:41.251936900+08:00" level=warning msg="failed to load plugin io.containerd.snapshotter.v1.btrfs" error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.btrfs must be a btrfs filesystem to be used with the btrfs snapshotter"
time="2020-05-30T11:04:41.253358200+08:00" level=warning msg="failed to load plugin io.containerd.snapshotter.v1.aufs" error="modprobe aufs failed: "modprobe: FATAL: Module aufs not found in directory /lib/modules/4.19.104-microsoft-standard\n": exit status 1"
time="2020-05-30T11:04:41.253742200+08:00" level=warning msg="could not use snapshotter zfs in metadata plugin" error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.zfs must be a zfs filesystem to be used with the zfs snapshotter: skip plugin"
time="2020-05-30T11:04:41.253750200+08:00" level=warning msg="could not use snapshotter btrfs in metadata plugin" error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.btrfs must be a btrfs filesystem to be used with the btrfs snapshotter"
time="2020-05-30T11:04:41.253757100+08:00" level=warning msg="could not use snapshotter aufs in metadata plugin" error="modprobe aufs failed: "modprobe: FATAL: Module aufs not found in directory /lib/modules/4.19.104-microsoft-standard\n": exit status 1"
time="2020-05-30T11:04:41.275727500+08:00" level=warning msg="Running iptables --wait -t nat -L -n failed with message: `# Warning: iptables-legacy tables present, use iptables-legacy to see them\niptables v1.8.4 (nf_tables):  CHAIN_ADD failed (No such file or directory): chain PREROUTING\nChain PREROUTING (policy ACCEPT)\ntarget     prot opt source               destination         \n\nChain INPUT (policy ACCEPT)\ntarget     prot opt source               destination         \n\nChain POSTROUTING (policy ACCEPT)\ntarget     prot opt source               destination         \n\nChain OUTPUT (policy ACCEPT)\ntarget     prot opt source               destination`, error: exit status 4"
time="2020-05-30T11:04:41.295501400+08:00" level=info msg="stopping event stream following graceful shutdown" error="<nil>" module=libcontainerd namespace=moby
time="2020-05-30T11:04:41.295907700+08:00" level=info msg="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: failed to create NAT chain DOCKER: iptables failed: iptables --wait -t nat -N DOCKER: iptables v1.8.4 (nf_tables):  CHAIN_ADD failed (No such file or directory): chain PREROUTING

在错误信息中可以提取到几点主要的问题:

  • iptables中PREROUTING链添加规则失败
  • 也许是内核版本导致的部分组件加载失败

先来看一下iptables的问题:

➜  log sudo iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
# Warning: iptables-legacy tables present, use iptables-legacy to see them
iptables v1.8.4 (nf_tables):  CHAIN_ADD failed (No such file or directory): chain PREROUTING

这里说规则添加失败是iptables-legacy提示的,我们切换到它看看。

➜  log 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

这样我们默认使用的iptables就是iptables-legacy了。

重新启动docker试试看。

➜  log sudo service docker start
Starting Docker: docker.
➜  log sudo service docker status
Docker is running.
➜  log sudo service docker status
Docker is running.
➜  log docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
➜  log docker -v
Docker version 19.03.10, build 9424aeaee9

可以看到docker已经没有问题了。

拉一个镜像试试。

➜  log docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
df20fa9351a1: Pull complete
Digest: sha256:185518070891758909c9f839cf4ca393ee977ac378609f700f60a771a2dfe321
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest

原因分析:

这里默认使用的是iptables-nft,命令是nft。它的部分命令参数已和我们常用的iptables不一样了,可以使用iptables-translate来查看。

➜  log iptables-translate -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
nft add rule ip filter INPUT tcp dport 22 ct state new counter accept

而docker可能还没有针对新版的iptables修改程序,所以导致了docker的启动失败,我们只要将iptables的版本切到旧版就可以了。

分享