容器启动直接退出,想进入容器调试改怎么办
使用过docker的朋友大概率会遇到docker启动容器失败或执行完直接退出的情况,如果我想进入容器手动执行命令调试,该怎么办呐?
docker容器启动失败正常都是由于启动主进程退出导致的,主进程启动命令往往都是由镜像dockerfile文件最后的entrypoint或cmd定义的,此时可覆盖主进程启动命令,更换一个挂起的命令即可。我常用挂起命令:/bin/bash
所以,我们要解决的核心问题就是:如何使用挂起命令覆盖entrypoint或cmd定义的容器主进程命令?
先上结论(适用所有镜像)
1. docker run -it --entrypoint /bin/bash镜像,执行后直接进入容器。
2. 若docker-compose启动容器,则需要修改docker-compose.yml文件,在对应服务下增加如下高亮显示信息;然后docker-compose重新up
version: '3'
services:
cmd:
image: 镜像
container_name: 容器名
entrypoint:
- tail
- -f
- /dev/null执行命令进入容器 docker exec -it 容器名 /bin/bash
以下为详细分析过程:
查看镜像的dockerfile文件(docker history --no-trunc image),检查最后容器启动主进程的命令是什么样的,entrypoint?cmd?还是它们的组合?覆盖方式稍有不同。为方便演示,我构造了一个简单dockerfile文件做案例。
docker run 覆盖容器主进程命令
docker run 使用-it交互参数,覆盖命令/bin/bash
cmd
from centos:latest maintainer quanling cmd ["echo","hello world"]
如果使用上面的文件创建镜像test:cmd,使用history命令查看容器主进程命令,下方橙色标记部分
[root@localhost docker]# docker history --no-trunc test:cmd image created created by size comment sha256:694d5f2d8809ef2847a9b6fd46efed49ab59aa6466784a1e783beb25c2f6c16e 31 seconds ago /bin/sh -c #(nop) cmd ["echo" "hello world"] 0b sha256:6dcafb4f0c8d93e8793f84bb837ef26ed6293c156dafafbbc520e55ed601a09e 16 minutes ago /bin/sh -c #(nop) maintainer quanling 0b sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6 3 months ago /bin/sh -c #(nop) cmd ["/bin/bash"] 0b <missing> 3 months ago /bin/sh -c #(nop) label org.label-schema.schema-version=1.0 org.label-schema.name=centos base image org.label-schema.vendor=centos org.label-schema.license=gplv2 org.label-schema.build-date=20210915 0b <missing> 3 months ago /bin/sh -c #(nop) add file:805cb5e15fb6e0bb0326ca33fd2942e068863ce2a8491bb71522c652f31fb466 in /
运行容器后成功打印出hello world后容器直接退出。容器状态为exited(0)。此时容器启动的主进程为橙色标记部分
[root@localhost docker]# docker run --name cmd test:cmd hello world [root@localhost docker]# docker ps -a container id image command created status ports names 6bc94359c4fd test:cmd "echo 'hello world'" 4 seconds ago exited (0) 3 seconds ago cmd
若想让容器一直up状态,方便进入容器进一步操作,需要使用挂起命令覆盖cmd ["echo","hello world"],
方法1:在命令中增加绿色高亮部分代码(额外增加-it选项可直接进入容器)。进入容器成功
[root@localhost docker]# docker run -it --name upcontainer test:cmd /bin/bash [root@9351844319e3 /]#
更换tty窗口,查看容器状态up。此时容器启动的主进程入橙色标记部分,说明覆盖cmd成功
[root@localhost ~]# docker ps -a container id image command created status ports names 9351844319e3 test:cmd "/bin/bash" 11 seconds ago up 10 seconds upcontainer
方法2:在命令中增加绿色高亮部分代码(额外增加-it选项可直接进入容器)。进入容器成功
[root@localhost docker]# docker run --name upcontainer -it --entrypoint /bin/bash test:cmd [root@50763cf9a838 /]#
更换tty窗口,查看容器状态up。此时容器启动的主进程入橙色标记部分,说明覆盖cmd成功
[root@localhost ~]# docker ps container id image command created status ports names 50763cf9a838 test:cmd "/bin/bash" about a minute ago up about a minute upcontainer
entrypoint
from centos:latest maintainer quanling entrypoint ["echo","hello world"]
如果使用上面的文件创建镜像test:entrypoint
运行容器后成功打印出hello world后容器直接退出。容器状态为exited(0)。此时容器启动的主进程入橙色标记部分
[root@localhost docker]# docker run --name entrypoint test:entrypoint hello world [root@localhost docker]# docker ps -a container id image command created status ports names e6cf335c5c09 test:entrypoint "echo 'hello world'" 8 seconds ago exited (0) 6 seconds ago entrypoint
若想让容器一直up状态,方便exec进入容器进一步操作,需要使用挂起命令覆盖entrypoint["echo","hello world"],模仿上面的操作,结果如下,容器exited状态(--no-trunc显示全输出信息)
[root@localhost docker]# docker run --name upcontainer test:entrypoint /bin/bash hello world /bin/bash[root@localhost docker]# docker ps -a --no-trunc container id image command created status ports names 0476c3014fa4c28615b72c231971c6b5186a310f9b2f5cae466643d65b236c34 test:entrypoint "echo 'hello world' /bin/bash" 2 minutes ago exited (0) 2 minutes ago upcontainer e6cf335c5c09df35845f40abfd81594e17b3457891128ee2108414d7573e62a3 test:entrypoint "echo 'hello world'" 7 minutes ago exited (0) 7 minutes ago entrypoint
我们想执行的挂起命令并未覆盖entrypoint命令,反而作为echo命令的参数部分一起输出了。因为覆盖entrypoint命令需要使用--entrypoint设置(额外增加-it选项可直接进入容器),进入容器成功。
[root@localhost docker]# docker run -it --entrypoint /bin/bash --name upcontainer test:entrypoint [root@4fe14a5e7bd1 /]#
更换tty窗口,查看容器状态up。此时容器启动的主进程入橙色标记部分,说明覆盖entrypoint成功
[root@localhost ~]# docker ps -a container id image command created status ports names 4fe14a5e7bd1 test:entrypoint "/bin/bash" 11 seconds ago up 10 seconds upcontainer e6cf335c5c09 test:entrypoint "echo 'hello world'" 14 minutes ago exited (0) 14 minutes ago entrypoint
entrypoint&cmd
from centos:latest maintainer quanling entrypoint ["echo"] cmd ["hello world"]
如果使用上面的文件创建镜像test:mixed。使用history命令查看容器主进程命令,下方橙色标记部分
[root@localhost docker]# docker history --no-trunc test:mixed image created created by size comment sha256:2c1f8303382cb221fac04a76234d0b1afe3a513205267afe2d01f39006877be8 24 seconds ago /bin/sh -c #(nop) cmd ["hello world"] 0b sha256:13608f257d7b6d1ae771af1aec482b7b87650703648a4ac5c03e8715f78c0079 25 seconds ago /bin/sh -c #(nop) entrypoint ["echo"] 0b sha256:6dcafb4f0c8d93e8793f84bb837ef26ed6293c156dafafbbc520e55ed601a09e 2 hours ago /bin/sh -c #(nop) maintainer quanling 0b sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6 3 months ago /bin/sh -c #(nop) cmd ["/bin/bash"] 0b <missing> 3 months ago /bin/sh -c #(nop) label org.label-schema.schema-version=1.0 org.label-schema.name=centos base image org.label-schema.vendor=centos org.label-schema.license=gplv2 org.label-schema.build-date=20210915 0b <missing> 3 months ago /bin/sh -c #(nop) add file:805cb5e15fb6e0bb0326ca33fd2942e068863ce2a8491bb71522c652f31fb466 in / 231mb
运行容器后成功打印出hello world后容器直接退出。容器状态为exited(0)。此时容器启动的主进程为橙色标记部分
[root@localhost docker]# docker run --name mixed test:mixed hello world [root@localhost docker]# docker ps -a container id image command created status ports names 22362d314132 test:mixed "echo 'hello world'" 4 seconds ago exited (0) 3 seconds ago mixed
若想让容器一直up状态,方便进入容器进一步操作,需要覆盖etrypoint和cmd中命令,在命令中增加绿色高亮部分代码(额外增加-it选项可直接进入容器)。查看执行结果
[root@localhost docker]# docker run -it --name upcontainer test:mixed /bin/bash /bin/bash [root@localhost docker]# docker ps -a container id image command created status ports names df18afb54646 test:mixed "echo /bin/bash" 6 seconds ago exited (0) 5 seconds ago upcontainer 22362d314132 test:mixed "echo 'hello world'" 3 minutes ago exited (0) 3 minutes ago mixed
执行发现容器为exited状态,打印出“/bin/bash”后容器退出。说明该操作仅仅覆盖了cmd ["hello world"]部分,保留了entrypoint ["echo"]部分。正确的操作应该使用--entrypoint设置(额外增加-it选项可直接进入容器),进入容器成功。
[root@localhost docker]# docker run -it --entrypoint /bin/bash --name upcontainer test:mixed [root@deb56cf88e89 /]#
更换tty窗口,查看容器状态up。此时容器启动的主进程入橙色标记部分,说明覆盖entrypoint成功
[root@localhost ~]# docker ps -a container id image command created status ports names deb56cf88e89 test:mixed "/bin/bash" about a minute ago up about a minute upcontainer 22362d314132 test:mixed "echo 'hello world'" 8 minutes ago exited (0) 8 minutes ago mixed
docker-compose中的覆盖主进程命令
有些容器是使用docker-compose来启动容器的,按照dockerfile文件的不同,docker-compose中的修改不同,覆盖命令 tail -f /dev/null
利用上面三个镜像,编写docker-compose.yml文件
version: '3'
services:
cmd:
image: test:cmd
container_name: cmd
entrypoint:
image: test:entrypoint
container_name: entrypoint
mixed:
image: test:mixed
container_name: mixed启动三个镜像的服务容器,都执行后退出exited状态。容器主进程见下方橙色高亮部分
[root@localhost docker]# docker-compose up -d starting cmd ... done creating entrypoint ... done creating mixed ... done [root@localhost docker]# docker ps -a container id image command created status ports names 7519cbfb6ef8 test:mixed "echo 'hello world'" 40 seconds ago exited (0) 36 seconds ago mixed d1c2709a0173 test:entrypoint "echo 'hello world'" 40 seconds ago exited (0) 36 seconds ago entrypoint e2206ea2cfc1 test:cmd "echo 'hello world'" 2 minutes ago exited (0) 37 seconds ago cmd
entrypoint命令
在docker-compose.yaml 文件中每个服务下添加以下绿色高亮区域命令,以覆盖原来docker中的命令
version: '3'
services:
cmd:
image: test:cmd
container_name: cmd
entrypoint:
- tail
- -f
- /dev/null
entrypoint:
image: test:entrypoint
container_name: entrypoint
entrypoint:
- tail
- -f
- /dev/null
mixed:
image: test:mixed
container_name: mixed
entrypoint:
- tail
- -f
- /dev/null重新启动容器,容器全部为up状态,主程序命令被替换为"tail -f /dev/null"
[root@localhost docker]# docker-compose up -d starting mixed ... done starting cmd ... done recreating entrypoint ... done [root@localhost docker]# docker ps -a container id image command created status ports names 2d4682226bb0 test:cmd "tail -f /dev/null" 4 seconds ago up 2 seconds cmd c3870ab0d462 test:mixed "tail -f /dev/null" 31 seconds ago up 28 seconds mixed 7320deecd45a test:entrypoint "tail -f /dev/null" 59 seconds ago up 55 seconds entrypoint
在docker-compose.yaml 文件中每个服务下添加以下绿色高亮区域命令
version: '3'
services:
cmd:
image: test:cmd
container_name: cmd
command: tail -f /dev/null
entrypoint:
image: test:entrypoint
container_name: entrypoint
command: tail -f /dev/null
mixed:
image: test:mixed
container_name: mixed
command: tail -f /dev/null重新启动容器,查看容器状态,及主程序命令
[root@localhost docker]# docker-compose up -d cmd is up-to-date ... done recreating entrypoint ... done recreating mixed ... done [root@localhost docker]# docker ps -a --no-trunc container id image command created status ports names bf67da0ba9815a013a2005d61daa223e31586bf1cde279933ba71d0148c721ff test:mixed "echo tail -f /dev/null" about a minute ago exited (0) about a minute ago mixed f019610b1aedb54904704227ae661f421786b72ecc9e3b35154442c4717afcb0 test:entrypoint "echo 'hello world' tail -f /dev/null" about a minute ago exited (0) about a minute ago entrypoint 224bc6db4563531c68947a38acbf3418c43149b2ef6a92565f940a98ab1a9b1e test:cmd "tail -f /dev/null" 10 minutes ago up 10 minutes cmd
分析结论
使用commad命令,结果仅test:cmd中命令被替换;test:entrypoint镜像未被覆盖,且commad命令作为参数传入;test:mixed镜像仅cmd部分命令被替换,entrypoint部分未被替换。与docker run运行结果一致。
补充
容器up状态时,执行exec命令进入容器
# docker exec -it 容器名 /bin/bash
容器内查看相关配置是否符合预期,手动执行镜像原entrypoint/cmd命令跟着日志进行调试
镜像往往很精简,不包含yum、vi 等命令,导致需要修改配置进行调试受阻,除安装所需命令这个麻烦的方法外,还可以在容器外使用docker cp命令
$ docker cp 容器名:文件完整路径 本地路径 #容器内文件copy到本地
$ docker cp 本地文件容器名:文件完整路径 #本地文件copy到容器内
$ docker run -it --rm --entrypoint="" 容器名 /bin/bash
到此这篇关于docker容器直接退出,如何进入容器调试的文章就介绍到这了,更多相关docker容器直接退出内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论