You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# docker run -it hello-world
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "process_linux.go:303: getting the final child's pid from pipe caused \"EOF\"": unknown.
对应的 dockerd 日志:
ERRO[2019-07-09T02:00:58.717968000+08:00] stream copy error: reading from a closed fifo
ERRO[2019-07-09T02:01:00.342200600+08:00] f91be3566b127aa49acc2021701035b2fadfa709a313d3f255999471ae309924 cleanup: failed to delete container from containerd: no such container
ERRO[2019-07-09T02:01:00.451686200+08:00] Handler for POST /v1.39/containers/f91be3566b127aa49acc2021701035b2fadfa709a313d3f255999471ae309924/start returned error: OCI runtime create failed: container_linux.go:345: starting container process caused "process_linux.go:303: getting the final child's pid from pipe caused \"EOF\"": unknown
# docker version
Client:
Version: 17.09.0-ce
API version: 1.32
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:42:18 2017
OS/Arch: linux/amd64
Server:
Version: 17.09.0-ce
API version: 1.32 (minimum version 1.12)
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:40:56 2017
OS/Arch: linux/amd64
Experimental: false# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 17.09.0-ce
Storage Driver: overlay2
Backing Filesystem: <unknown>
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 06b9cb35161009dcb7123345749fef02f7cea8e0
runc version: 3f2f8b84a77f73d38244dd690525642a72156c64
init version: 949e6fa
Kernel Version: 4.4.0-17134-Microsoft
Operating System: Ubuntu 16.04.2 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 15.89GiB
Name: DESKTOP-31U4I5S
ID: 35XV:BUEF:HFQE:DFHI:5HVO:Y40P:2E2V:DC3L:YBAK:JGKR:WD34:OYPZ
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: No memory limit support
WARNING: No swap limit support
WARNING: No kernel memory limit support
WARNING: No oom kill disable support
WARNING: No cpu cfs quota support
WARNING: No cpu cfs period support
WARNING: No cpu shares support
WARNING: No cpuset support
启动容器看下效果:
docker run -it --rm hello-world
docker run -it --rm --name nginx --network host nginx
curl 127.0.0.1
启动服务遇到的问题
最初,直接启动 dockerd 会报下面的错误:
# dockerd
INFO[2019-07-05T16:46:00.707322400+08:00] libcontainerd: new containerd process, pid: 1573
WARN[0000] containerd: low RLIMIT_NOFILE changing to max current=1024 max=65536
INFO[2019-07-05T16:46:01.739948500+08:00] [graphdriver] using prior storage driver: overlay2
INFO[2019-07-05T16:46:01.782012800+08:00] Graph migration to content-addressability took 0.00 seconds
WARN[2019-07-05T16:46:01.782616800+08:00] Your kernel does not support cgroup memory limit
WARN[2019-07-05T16:46:01.782894700+08:00] Unable to find cpu cgroup in mounts
WARN[2019-07-05T16:46:01.783166700+08:00] Unable to find blkio cgroup in mounts
WARN[2019-07-05T16:46:01.783375800+08:00] Unable to find cpuset cgroup in mounts
WARN[2019-07-05T16:46:01.783676600+08:00] mountpoint for pids not found
Error starting daemon: Devices cgroup isn't mounted
# docker exec -it nginx sh
oci runtime error: exec failed: container_linux.go:265: starting container process caused "could not create session key: function not implemented"
前言
最近看一篇文章中提到 WSL 中已经支持 Docker 运行了,最初不以为意以为还是千篇一律的标题党 ( Docker Client + Docker Desktop for Windows ) ,后来尝试之后发现确实可行,本文在此记录一些遇到的问题。
关于版本
系统最低版本要求: 1803 (
17134
) 。1803 下可用 Docker 版本:
17.03.0
~17.09.0
使用高版本的 Docker 拉取镜像时会报下面的错误:
原因见 这里 ,issue 中说这个问题应该在 17666 版本已经修复了。
1809 下可用 Docker 版本:
17.03.0
~18.06.1
使用高版本的 Docker 创建容器时会报下面的错误:
对应的 dockerd 日志:
安装低版本的就好了
最终方案 ( 参考 )
安装 Docker
修改配置文件
启动 Docker ( 使用 管理员权限 打开 CMD 或者 PowerShell 来运行 WSL )
查看状态:
启动容器看下效果:
启动服务遇到的问题
最初,直接启动 dockerd 会报下面的错误:
解决办法:
# 安装并挂载 cgroup sudo apt -y install cgroupfs-mount sudo cgroupfs-mount
再启动还会报错:
原因是 iptables 功能缺失,禁用就好了 ( 参考 ) 。
其实,只有针对 172.17.0.0/16 网段执行时不会报错的,而且 MASQUERADE 规则是可以生效的 ( 容器可以访问外网 ) 。
所以,安装完 docker 后先不禁用 iptables 来启动一遍 dockerd ,让它自动生成 docker0 网络并自动配置 SNAT ,之后就禁用 iptables 启动 dockerd ,这样用到 docker-compose 或者创建其他网桥网络时就不会报错了,只不过其他网络无法访问外网 ( 这个问题后面来解决 ) 。
然后还会报错:
Error starting daemon: Error initializing network controller: Error creating default "bridge" network: permission denied
原因是创建网桥的命令权限不足,比如第一次创建的 docker0 和 之后使用
docker network create
命令创建的自定义网络都需要 管理员权限 。解决办法: 以 管理员权限 打开 CMD 来运行 dockerd 。
顺带提一点,WSL 下有些缺失的功能可能已经实现了部分实验功能 ( 比如 ) ,在 管理员权限 下可以试试看。
网络配置
ping 容器
Windows 防火墙添加入站规则 - ICMPv4 类型的协议 ( 参考 )
端口映射的问题
比如启动一个 Nginx 服务,做端口映射,在 Win10 1803 上会发现无法访问 127.0.0.1:3000
接着在 Win10 1809 上试了是可以访问的,然而换成 Tomcat 容器后就又不行了,而且 宿主机 也无法通过 容器 的 内网 IP + 端口 来访问,怀疑是网桥或者路由表的配置有缺失。于是定制了一个安装各种网络工具包的镜像进行各种测试,发现把 Tomcat 的监听端口改为 80 就可以了。通过这个现象想起来可能是防火墙的原因,而 WSL 中 iptables 功能有缺失应该是不起作用的,那么问题应该是出在 Win10 的防火墙上。果然,在防火墙中添加 入站规则 放行容器中的监听端口 ( 比如 8080 ) 就解决了,我猜应该是容器中使用了 Windows 下的防火墙做拦截,而 宿主机 却被当成了外来者。
注意:
容器访问外网
上面也提到了 iptables 功能缺失,就做不了 源网络地址转换 ( SNAT / MASQUERADE ) ,这就导致了容器不能访问外网 ( 容器之间也无法跨网路访问 ) 。
# 新建一个自定义网络 docker network create --subnet 172.18.0.0/16 test_net
目前有两种不是很完美的办法来临时解决:
在宿主机搭建代理服务器,在容器中使用代理连接:
启动容器的时候配置环境变量
http_proxy
和https_proxy
当然,也可以修改配置文件,对之后启动的所有容器生效 ( 参考 )
这种方式仅限于 HTTP 请求 ( 而且只能使用当前网络的网关 IP 来访问代理 ) ,换成低层次的 TCP 或者 UDP 通讯可能就不行了。
类似于 Windows 上开 WiFi 共享 的操作。
Docker 创建网络时对应会在 Windows 下创建网卡 ( 比如 IP 为 172.18.0.1 ) ,只要把无线网卡或者有线网卡的网络共享给这个新建的网卡,容器就可以通过本地网卡来访问外网了。
具体步骤:
这种方式比起前一种方式支持的网络更完善,缺点就是只能共享网络给一个网卡,而且无法访问其他网络的容器。
如果使用域名无法访问,可能是容器内 DNS 解析失败,换个 DNS 服务器 ( /etc/resolv.conf ) 。
另外,还遇到过一个不是必现的问题,网桥有时候会变成 169.254.158.185/16 这种很神奇的 IP ,暂时还没找到原因。如果遇到这个问题,可以关掉 Docker 后手动删除网桥,让它重新创建。
其实,网络问题的排查无非就是几个点:端口监听,IP 分配、路由表、防火墙、DNS、NAT 。
其他问题
镜像加速器 可能会不能正常使用 (
1803
+17.09.1+
)表现形式为 pull 镜像的时候先从 镜像站 下载一遍,再回 官方源站 下载一遍。
暂无解决办法,如果 源站 下载过慢可以使用 HTTP 代理 或者 VPN 。
关于 WSL 下 docker-compose 的用法和问题参考我的另一篇 文章 。
不支持 docker exec 命令
解决办法: 使用 nsenter 命令进入容器 ( 参考 )
应该已经内置
nsenter
命令了,如果没有的话自行安装。可以写一个函数来简化调用:
再次调用就简单多了:
容器内文件读写权限有问题
可能是文件系统的问题也可能是容器用户的权限问题
比如运行数据库之类的容器会提示权限不足的错误,比如:
从错误信息看出是 tmp 目录没有权限,可以在启动容器的时候使用 挂载数据卷 的方式来解决:
docker run -it --rm --network host -v /tmp:/tmp -v ~/.neo4j/certificates:/var/lib/neo4j/certificates neo4j
当然,权限不足的目录可能不止这么一个,需要自己一个个去排查,还是比较麻烦的。
非 docker0 网络下 --link 失效 ( 不会写入配置到 /etc/hosts 中 )
其他玩法
查资料的过程中发现了另一篇文章—— 用 WSL 运行 Docker 镜像 ,虽然没有跑通文章中的例子,但是思路还是很有启发性的。从文章中用法来看,WSL 的架构和 Docker 还是比较类似的,WSL 提供基本的 内核 ,商店中的各种 发行版 等价于 镜像 用来提供系统目录和软件包,而每个 WSL 实例则等价于 容器 。
如果 WSL 后续能够原生支持从 Docker Hub 下载镜像,同时支持类似于 Docker 一样的命令来管理 WSL 实例,岂不是一件很酷的事?
参考文章
Docker Running Seamlessly in Windows Subsystem Linux
wsl中使用原生docker
WSL/issues/2291#issuecomment-383698720
docker is running natively on wsl
Docker 相关资料
写在最后
在 WSL 上成功运行 Docker 其实就几分钟的事,不过为了解决上面提到的一些问题又断断续续花了几天时间,重装了几十遍 WSL,也不断测试并修正了文中的例子,希望没有纰漏吧。
自从写完 Windows10内置Linux子系统初体验 一文已是两年过去了,见证了 WSL 从鸡肋到现在基本满足使用的过程,虽然还不是很完美,但它一直在不断完善,而我也会持续关注并更新下去。
转载请注明出处:https://www.jianshu.com/p/20ebdbf68744
The text was updated successfully, but these errors were encountered: