云主机OS版本 CentOS 7.6 Docker版本 Docker CE 19.03.9
今天学习k8s的时候,实操过程中改了daemon的配置
#找到ExecStart=xxx,在这行上面加入一行,内容如下:(k8s的网络需要)
ExecStartPost=/sbin/iptables -I FORWARD -s 0.0.0.0/0 -j ACCEPT
$ systemctl daemon-reload
$ service docker restart
之后便直接
重启了docker.service,是的你没有听错,我没有去docker stop容器,而是直接重启docker.service,重启完之后我才意识到这样操作不对,因此就有一个容器死活就是启动不了,一启动过几秒就自动退出,然后自动重启...(ps.容器自动重启配置命令:docker container update --restart=always [CONTAINER NAME] 参考:docker内部容器自动重启配置 将docker容器设为自启动和取消容器自启动)
docker container update --restart=always 容器名字
操作实例如下:
[root@localhost mnt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
46cdfc60b7a6 nginx "nginx -g 'daemon ..." About a minute ago Up 42 seconds 80/tcp n3
79d55a734c26 nginx "nginx -g 'daemon ..." About a minute ago Up 42 seconds 80/tcp n2
f7b2206c019d nginx "nginx -g 'daemon ..." About a minute ago Up 46 seconds 80/tcp n1
[root@localhost mnt]# docker container update --restart=always n1
n1
[root@localhost mnt]# systemctl restart docker
[root@localhost mnt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
46cdfc60b7a6 nginx "nginx -g 'daemon ..." 2 minutes ago Exited (0) 5 seconds ago n3
79d55a734c26 nginx "nginx -g 'daemon ..." 2 minutes ago Exited (0) 5 seconds ago n2
f7b2206c019d nginx "nginx -g 'daemon ..." 2 minutes ago Up 2 seconds 80/tcp n1
一开始我还怀疑过容器假死的情况,但是根本不是这种情况,因为它不符合以下几种情况:
#在使用docker部署我们的服务时,偶尔会遇到这种情况,使用如下命令判断:
docker ps 显示容器状态正常,但是对外服务已经不可用
docker stats 没有任何反应
docker stop CONTAINER_ID 没有任何反应
docker restart CONTAINER_ID 也没有任何反应
docker exec -it –user root CONTAINER_ID /bin/bash 也没有任何反应
docker logs CONTAINER_ID --tail 111 -f 也没有任何反应
docker-compose命令也提示响应超时,不可用
所以排除假死的原因.
之后排查过程中,通过docker logs [CONTAINER ID]查看日志根本看不出启动过程中报的错误信息,一开始我怀疑的是容器内的服务端口被占用
#docker 查看端口被占用进程
lsof -i:8080(或者netstat -antp|grep 8080)
发现正常,没有被占用. (docker top [CONTAINER ID]命令也用过了,报错Error response from daemon: Container e08201b591cdccd198fa32c4eedbda4a9ca6c81ce2c066e885c592aede52a8a6 is not running,因为容器没运行.)
后面又开始觉得是容器内部服务里面占用8080端口,毕竟8080端口太容易被占用,所以尝试修改容器服务内部的配置文件,又一个问题冒出来了,就是进不去容器内部bash,因为容器没有运行,虽然有几秒的短暂时间可以进得去,但还没等你找到想改的端口配置文件就自动退出了,docker exec命令就这样,一旦容器挂了,exec也会跟着自动退出到宿主机.那怎么办呢?
为了验证是容器内部的报的错的想法,我把这个问题容器用docker commit提交到一个新的镜像,然后用docker run -itd --name xxx -p xxxx:8080 --restart=always [IMAGES NAME]:[TAG]
基于新镜像运行一个新的容器进去改变(修复)配置文件。再通过新的容器再提交一个新的镜像,然后在基于新的镜像重新启动容器(同最初的容器)(参考:如何修复无法启动的docker容器).结果还是自动退出..
但是有一点肯定的,就是容器内部的服务有问题,可能是在启动过程中出了问题
那既然Docker容器无法启动,里面的配置文件如何修改?
运行命令 docker inspect [CONTAINER ID] ,可以找到如下的内容
看到MergedDir, cd到MergedDir,你会惊奇的发现,他和我们容器里的目录结构是一样的(参考:Docker容器无法启动,里面的配置文件如何修改)
注意: 如果容器stop状态,cd是进不去的,会提示:
-bash: cd: /var/lib/docker/overlay2/5f7b60d2ed5b419f72e76155e1a08f5e55b0b92cad46186eb5d847f25e0be432/merged: No such file or directory
,那么这个时候可以docker start启动,启动后再次进去了不会像docker exec那样容器停了,会被迫退出.
继续cd到WORKDIR 比如我的是:/app/mblog (Dockerfile配置的工作目录),是不是和docker exec -it xxx bash 进去的目录一样呢?对!没错,一模一样!
事实上,本网站中的图片也可以利用这种方式通过登录sftp工具进行快速替换
于是我赶紧cd logs, tail -f blog-2022-09-22.log查看启动日志
果然在报错!!!
原来是一直连不上数据库,报Public Key Retrieval is not allowed
错误.于是我用连接工具DBeaver连了一下数据库发现可以连上,然后再回头看日志的时候发现启动成功了?!!!(为什么又启动了,是因为前面配置了自动重启)
虽然很怪异,但是解决这个问题的心路历程还是有必要记录一下的,毕竟关于Docker这块又成长了一点.
(完)
注意:本文归作者所有,未经作者允许,不得转载