现象
表象是容器无法 stop, restart, rm , 登录主机后执行
1 | [root@orderer0 /home/blockchain/peer0.org1/conf]# docker-compose down |
临时处理
检查 network
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46[root@orderer0 /home/blockchain]# docker network inspect conf_default
[
{
"Name": "conf_default",
"Id": "412177b0cf14414b191fc99ab4411d65c201e52424217476eb6b5cc861a5b603",
"Created": "2019-11-21T22:08:45.523133411+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"19ffaa8a2c03891c1883f962e0076a04ec9461bfc8364d60052e34e5464e9762": {
"Name": "peer0.org1", # 关联的 Containers name
"EndpointID": "1f82857982ba62ce6003e15bb140686a24859ca7374bca110ab7e481af56c855",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
},
"9c7dd8270317bb09aac306a9aa952b05fff5fa0a65ef3f4f7c4e1a5d8c03bf1e": {
"Name": "dev-peer0.org1.finblockchain.cn-fft-2.0.0", # 关联的 Containers name
"EndpointID": "33dbba6e9cc513d4e0b293fa7f2d4415bb1c13aa4d1c0c87f86d2063409b7bd1",
"MacAddress": "02:42:ac:15:00:03",
"IPv4Address": "172.21.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]断开关联的 Containers name 网络
1
2# docker network disconnect -f net_default peer0.org1
# docker network disconnect -f net_default dev-peer0.org1.finblockchain.cn-fft-2.0.0然后就可以正常执行
1
# docker-compose down
根本解决
在
docker.service
中加上:1
2
3
4
5
6
7
8
9
10
11
12[Service]
MountFlags=slave
```
来保证 docker 及 container 运行在 私有 的 **mount namespace** 上。当 docker 以这种方式启动时,可以使用 `grep /mnt /proc/self/mountinfo` 来检测以这种方式启动的容器确实看不到 **mount point** 了,而之前遗留的挂载点仍然可以看到。
很多线上机器已经跑着业务容器不能重启 **docker daemon** 怎么办?
在生产中,需要尽可能保证所有的操作 不影响正在运行的业务容器。
所以,在已有条件下,既不能停止 nginx,又不能重启 **docker daemon**,唯一的方法只有在 `docker-compose down` 出错的情况下通过执行
```sh
# docker rm -f $(docker ps -a -q -f status=dead)来强制删除 dead container 了。虽然仍然会有错误信息提示,但是可以看到 Dead container 确实被删除了。之后可以正常运行
docker-compose up -d
有没有方法可以在不影响业务容器的前提下重新配置 docker daemon 呢?
docker 从 1.12.0 开始支持在 不重启 container 的情况下重启 docker daemon,只需要在 docker daemon 启动时增加 --live-restore=true
这个参数。可惜的是,该参数直到目前仍不支持 daemon reload(类似 nginx 的 reload 和 restart),只能重启 dockerd 后生效
本质
挂载点泄露实际上是 RHEL/CentOS 内核的一个 bug,目前预计会在 RHEL7.4 kernel 中修复
目前在 RHEL/CentOS 下需要在 docker.service 中增加 MountFlags=slave
来保证 mount namespace 是私有的,不会造成挂载点泄露。
另外,挂载点泄露在各种 storage driver 中都存在,比如最常见的 devicemeppaer
和 overlay
。
但是,目前 RHEL/CentOS 版本下 MountFlags=slave
和 --live-restore
两个给力的参数不能同时存在。因为 MountFlags=slave
会导致 docker daemon 每次重启时私有挂载命名空间都会发生变化,而 --live-restore
又相当于使得容器持有了变化之前的旧的挂载点信息,因此,当重启 docker daemon 之后,执行 docker exec
试图进入容器时会报错:
rpc error: code = 13 desc = invalid header field value "oci runtime error: exec failed: container_linux.go:247: starting container process caused \"process_linux.go:75: starting setns process caused \\\"fork/exec /proc/self/exe: no such file or directory\\\"\"\n"
值得一提的是,虽然无法进入容器,但是容器依旧工作正常并且 docker logs 也没问题。