问题概述
主机重启后,docker上的容器无法启动,报错如下
# docker restart nginx-proxy
Error response from daemon: Cannot restart container nginx-proxy: error creating overlay mount to /var/lib/docker/overlay2/7431ad53435c5cb52cc24ecc7263b580d4087e2c25e0d4c4c14c577a32ad3607/merged: invalid argument
问题排查
首先怀疑可能是镜像问题,于是尝试用同一个镜像去启动一个新的容器,可以正常启动成功,排除是镜像的问题
# docker run -itd --name test nginx:1.14
17a4ab4080dc347828e34b576de2d1922d16f6a0929d9eb5f513313df0a32609
接着看了docker的日志,没发现有用的信息
由于报错显示的是mount过程中出现了异常,所以接着排查了系统日志,发现如下报错
看到这段报错顿时有种熟悉感,system_u:object_r
这种字符串很明显跟selinux有关,于是怀疑环境中肯定是开启了selinux导致容器挂载异常无法启动
于是看了下selinux的状态,发现是disabled的状态。看到selinux是disabled的状态时,差点将selinux排除在外,还好上面的的报错我很确定是跟selinux有关
# getenforce
Disabled
为了验证是否跟selinux有关,我重新将selinux设置为启动状态,并重启了主机,果然容器可以启动成功
# docker restart nginx-proxy
nginx-proxy
此时问题还未解决,因为selinux需要关闭,所以还需要进一步查看容器为什么无法启动
接着再把selinux给关掉,再重启主机,果然容器又无法启动了
由于新的容器可以启动成功,而旧的容器则无法启动,所以怀疑是不是容器配置有什么不一样的地方,于是查看了下容器的配置,果然在容器的配置中发现了异常
cd /var/lib/docker/containers/<container_id>/
cat config.v2.json
从上图中可以发现, MountLabel和ProcessLabel中都携带了selinux的参数,于是将这两个参数的值都设置为空,然后重启docker(直接修改配置无法生效,需要重启docker才能生效),容器启动成功了!
# vi config.v2.json
...
...
"MountLabel":"","ProcessLabel":""
...
...
# systemctl restart docker
# docker ps |grep nginx
037bd8327183 nginx:1.14 "nginx -g 'daemon of…" About 18 hour ago Up 11 seconds nginx-proxy
至此问题解决
问题总结
该问题的主要原因是操作系统之前开启过selinux,在此前提下启动docker并创建了该容器,于是docker的启动参数中会携带某些selinux配置,随后又修改了/etc/selinux/config的配置,将selinux设置为disabled的状态,但是此时selinux的disabled还未生效,而要使selinux的disabled生效,需要重启主机。所以在重启主机前,selinux的状态还是开启的,容器都是能够正常运行。
当重启主机后,/etc/selinux/config下的配置就开始生效,selinux就会被设置为disabled的状态,此时容器的配置中还携带有selinux的配置,当启动容器时,会携带这些配置去访问selinux服务,此时selinux是不可用的状态,所以容器就会抛出异常无法启动。
解决方法:
- 重新启用selinux,然后重启主机即可。selinux 主要作用就是最大限度地减小系统中服务进程可访问的资源,但是如果对selinux不是很懂的情况下,开启selinux可能还会引起其他问题,此时建议采用第二种方法
- 修改容器的配置,将 MountLabel 和 ProcessLabel 两个参数的值设置为空
"MountLabel":"","ProcessLabel":""
,然后重启docker服务,容器即可修复