docker容器直接退出,如何进入容器调试-编程思维

使用过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

 


 


 

以下为详细分析过程:

查看镜像的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

Command命令

在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

 

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://www.cnblogs.com/sylvia-liu/p/14933776.html

.NET 微服务——CI/CD(3):镜像自动分发-编程思维

如何通过Jenkins完成镜像分发?基本做法是:打包镜像→上传镜像到仓库→脚本分发。镜像仓库也有很多,比如docker hub、Harbor等,今天这一篇讲一下基于阿里云镜像仓库的操作。 首先,准备一个阿里云镜像仓库,个人版是免费的。 然后下载这个插件: Publish Over SSH 这个插件主要用来远程登录

Docker 学习线路-编程思维

起因   之前的几篇博客,需要一定的docker知识(虽然可以直接上手),但是对于没有docker基础的人来说是不知道为什么要这样做的。   我把之前学习docker的步骤整理出来,希望可以帮助更多的人去学习docker。 目录:   1. Docker 基础     1.1 Docker 历史     1.2 Doc

聊聊docker那些端口问题-编程思维

今天来系统聊一聊docker的端口,常见的有容器内程序端口、容器端口、主机端口、Dockerfile中EXPOSE端口、docker-compose和docker run中的port等。 貌似很多端口,但连接时真实的端口仅程序端口和主机端口,其他都是对端口的声明,并不会实际开启端口的服务。 下面以nginx和redis

Console工具API-编程思维

$_          上个表达式的值 $0 - $4  最近选择的5个element $           doucment.querySelector $$         document.querySelectorAll $x         匹配xpath的element clear     清空 copy

嵌入式交叉编译GDB,结合vscode图形化调试C和C++代码 coredump定位段错误-编程思维

  第一部分:交叉编译GDB GDB源码下载路径:http://ftp.gnu.org/gnu/gdb/ 遇到的主要难点: 选择合适的GDB源码版本 我的mips-linux交叉编译器不支持C++11特性,所以我选择较老的GDB版本 //是不是不太明白我在说啥?自己去试错就知道了。我之前选择了GDB9.1版本,编译途

Windows下搭建FFmpeg开发调试环境-编程思维

背景 如果你是一个FFmpeg的使用者,那么绝大部分情况下只需要在你的程序中引用FFmpeg的libav*相关的头文件,然后在编译阶段链接相关的库即可。 但是如果你想调试FFmpeg内部相关的逻辑,或者分析FFmpeg源码,那么有一个可供单步调试FFmpeg的环境往往能使你事半功倍! 要说Windows下做C/C++开

Lua中如何实现类似gdb的断点调试--01最小实现-编程思维

说到Lua代码调试,最常用的方法应该就是加一堆print进行打印。print大法虽好,但其缺点也是显而易见的。比如效率低下,需要修改原有函数内部代码,在每个需要的地方添加print语句,运行一次只能获取一次信息,下次换个地方又得重新添加print语句。而且有时候,事先并不知道该去哪打印、或者打印什么内容,需要通过运行中

Lua中如何实现类似gdb的断点调试--02通用变量打印-编程思维

在前一篇01最小实现中,我们实现了Lua断点调试的的一个最小实现。我们编写了一个模块,提供了两个基本的接口:设置断点和删除断点。 虽然我们已经支持在断点进行变量的打印,但是需要自己指定层数以及变量索引,使用起来不是很方便。要进行upvalue打印的话,操作会更加麻烦。为了提升调试的方便性,我们决定封装一个通用的变量打印

Lua中如何实现类似gdb的断点调试--04优化钩子事件处理-编程思维

在第一篇的01最小实现中,我们实现了一个断点调试的最小实现,在设置钩子函数时只加了line事件,显然这会对性能有很大的影响。而后来两篇02通用变量打印和03通用变量修改及调用栈回溯则是提供了一些辅助的调试接口,并没有对钩子函数进行修改。 我们本篇将在钩子中引入call和return事件的处理,尝试对性能进行优化。 源码