問題概述
主機重啟后,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服務,容器即可修復