Docker容器调试应用程序

引言

因为Docker技术的火热,因此在工作中我们经常会以容器的方式来运行一个应用。每当容器无法成功运行或者想要对容器中的应用参数、应用配置以及应用启动进行深入研究时,当然希望能够像在宿主机上调试程序一样在容器中调试应用。容器的本质包括应用与应用运行所依赖的环境, 因此首先需要创建一个空壳容器(没有运行应用的应用容器),然后进入容器中调试应用。此处的空壳容器提供了应用运行所需的环境,进而可方便的在其中调试应用。实践环境:Centos7.2+Docker1.12.6。

容器启动命令介绍

比较规范的镜像的Dockerfile中通常会有ENTRYPOINT与CMD的定义(Docker官方推荐这样做)。因此容器的启动命令则为ENTRYPOINT所对应的脚本或可执行程序加上CMD中定义的内容。比如elasticsearch的Dockerfile定义的ENTRYPOINT与CMD分别为:ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["elasticsearch"],则创建的容器的启动命令为:/docker-entrypoint.sh elasticsearch;mysql的Dockerfile:ENTRYPOINT ["docker-entrypoint.sh"] CMD ["mysqld"],则创建的容器的启动命令为:/docker-entrypoint.sh mysqld。所以想要知道一个容器的启动命令需要首先了解其镜像的Dockerfile中ENTRYPOINT与CMD的定义。如何查看一个镜像的ENTRYPONT与CMD的值呢?一般采用如下两种方式:

  1. 查看镜像的Dockerfile

    比如查看zookeeper的Dockerfile,先在Docker仓库中找到zookeeper镜像,然后找到特定版本的Dockerfile
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["zkServer.sh", "start-foreground"]
  1. 通过 docker history 或 docker inspect 命令查看
    比如查看prom/prometheus:v1.8.0镜像的ENTRYPOINT与CMD信息
    docker history --no-trunc prom/prometheus:v1.8.0 (--no-trunc表示完整输出)

    上图仅展示一部分内容,可知prom/prometheus:v1.8.0镜像的ENTRYPOINT为:/bin/prometheus,CMD为:
    "-config.file=/etc/prometheus/prometheus.yml"
    "-storage.local.path=/prometheus"
    "-web.console.libraries=/usr/share/prometheus/console_libraries"
    "-web.console.templates=/usr/share/prometheus/consoles"

    docker inspect prom/prometheus:v1.8.0

    上图仅展示一部分内容,也可知prom/prometheus:v1.8.0镜像的ENTRYPOINT为:/bin/prometheus,
    CMD为:"-config.file=/etc/prometheus/prometheus.yml",
    "-storage.local.path=/prometheus",
    "-web.console.libraries=/usr/share/prometheus/console_libraries",
    "-web.console.templates=/usr/share/prometheus/consoles"

上述第一种方式适用于比较规范的镜像,这类镜像通常会提供清晰、具体的Dockerfile。第二种方式适用于各种镜像,尽管是不规范的镜像。通过history、inspect两个命令的任一个均可快速、方便的查看镜像的ENTRYPOINT与CMD的值。

不同类型镜像的调试举例

如果不作额外的设置,容器的启动命令则是镜像的ENTRYPOINT+CMD的方式。比如:

若要调试容器中的应用程序,则需额外的设置实现。docker run命令提供的--entrypoint参数能够覆盖Dockerfile中默认定义的ENTRYPOINT;docker run [OPTIONS] IMAGE [COMMAND] [ARG...]的COMMAND能够替换Dockerfile中定义的CMD。通过上面的示例可以发现,有的镜像的Dockerfile中ENTRYPOINT值为:/docker-entrypoint.sh,CMD为应用的可执行程序;有的镜像的Dockerfile中ENTRYPOINT值为应用的可执行程序,CMD为可执行程序的参数。因此针对不同的镜像想要创建空壳容器其方式是不同的。

  1. Dockerfile的ENTRYPOINT为/docker-entrypoint.sh,CMD为应用的可执行程序
    通常比较正式的官方镜像均会提供docker-entrypoint.sh脚本作为ENTRYPOINT,docker-entrypoint.sh脚本一般能够接收类似bash、sh的参数,因此对于这类镜像可以指定容器的COMMAND覆盖应用的二进制程序创建空壳容器。这里以elasticsearch:5.0.2镜像为例

    创建空壳容器es:
    docker run -itd --name es --network host elasticsearch:5.0.2 bash (alpine系统指定sh,非alpine系统可以指定bash or sh)

    查看空壳容器es中运行的进程:

    可见,es容器中运行的进程变为bash,并不是elasticsearch应用;此时es就为空壳容器,进入es容器调试elasticsearch应用就像在宿主机上调试程序

    进入es容器:

    es容器中调试elasticsearch应用程序:

    运行elasticsearch应用程序:
  2. Dockerfile的ENTRYPOINT为应用的可执行程序,CMD为可执行程序的参数
    这类镜像不能再简单的通过覆盖镜像的CMD来创建空壳容器了,因为docker run 的COMMAND是作为ENTRYPOINT指定的二进制程序的参数传入的,所以简单的指定COMMAND为bash或sh多数情况下是不行的,最好的方式是通过docker run的--entrypoint参数来覆盖镜像中指定的二进制可执行程序,使得创建的容器其内部的进程为entrypoint参数指定的bash or sh。这里以google/cadvisor:v0.27.2镜像(ENTRYPOINT: /usr/bin/cadvisor -logtostderr, CMD: null)为例

    创建空壳容器cadvisor:
    docker run -itd --name cadvisor --network host --entrypoint sh -v /var/lib/docker:/var/lib/docker:ro google/cadvisor:v0.27.2

    查看cadvisor容器的进程:

    进入cadvisor容器内调试应用:

    运行cadvisor应用程序:

    通过指定docker run的COMMAND为sh看能否成功创建空壳容器:

    可见,这种方式不能成功创建空壳容器

    上面是对两种类型的ENTRYPOINT创建空壳容器的举例说明,其实也可以对ENTRYPOINT不加以区分,即均通过docker run 的--entrypoint参数覆盖镜像中的ENTRYPOINT创建空壳容器。比如示例1中的elasticsearch:5.0.2镜像,指定--entrypoint bash创建空壳容器:
总结

容器其实是应用与应用运行所依赖的环境,创建空壳容器即提供了应用所需要的环境,进入此环境中可以调试应用,可以验证应用的各个参数,同样更可以像在宿主机中运行程序一样在此环境中运行应用,区别仅是容器与宿主机的两个环境。上面是对如何在容器中调试应用程序做的一些记录,希望与大家一起讨论、交流,一起学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343