Docker CMD in detail

Posted lenmom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker CMD in detail相关的知识,希望对你有一定的参考价值。

CMD

CMD 指令就是用于指定默认的容器主进程的启动命令的,我们直接 docker run -it ubuntu 的话,会直接进入 bash。我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release。这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息。

在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 ",而不要使用单引号。

如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:

CMD echo $HOME
在实际执行中,会将其变更为:

CMD [ "sh", "-c", "echo $HOME" ]

这就是为什么我们可以使用环境变量的原因,因为这些环境变量会被 shell 进行解析处理

提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出现的一个混淆。

Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念

一些初学者将 CMD 写为:

CMD service nginx start

然后发现容器执行后就立即退出了。甚至在容器内去使用 systemctl 命令结果却发现根本执行不了。这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器。

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西

而使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为

CMD [ "sh", "-c", "service nginx start"]

因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出。

正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:

CMD ["nginx", "-g", "daemon off"]

ENTRYPOINT

用于指定容器运行程序和参数,比较CMD:

FROM ubuntu:16.04
RUN apt-get update     && apt-get install -y curl     && rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "http://ip.cn" ]

若执行docker run myapp -i会认为-i是替代shell,所以会出错,必须用docker run myapp curl -s http://ip.cn -i, 若用ENTRYPOINT:

FROM ubuntu:16.04
RUN apt-get update     && apt-get install -y curl     && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

则可使用docker run myapp -i

以上是关于Docker CMD in detail的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(代码片段

Docker installation in sles SP2

一旦单击带有 in 片段的回收器列表项,如何将片段意向活动,以及如何获取回收器项目值?

Docker删除报错:Error response from daemon: conflict: unable to delete 08b152afcfae (must be forced)(代码片段

What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段

无需 Docker-in-Docker 的私有 Gitlab Runner 代码质量