共计 3546 个字符,预计需要花费 9 分钟才能阅读完成。
Dockerfile 用于自动化构建一个 docker 镜像。Dockerfile 里有 CMD 与 ENTRYPOINT 两个功能咋看起来很相似的指令,开始的时候觉得两个互用没什么所谓,但其实并非如此:
CMD 指令:
The main purpose of a CMD is to provide defaults for an executing container.
CMD 在容器运行的时候提供一些命令及参数,用法如下:
- CMD [“executable”,“param1”,“param2”] (exec form, this is the preferred form)
- CMD [“param1”,“param2”] (as default parameters to ENTRYPOINT)
- CMD command param1 param2 (shell form)
- 第一种用法:运行一个可执行的文件并提供参数。
- 第二种用法:为 ENTRYPOINT 指定参数。
- 第三种用法(shell form):是以”/bin/sh -c”的方法执行的命令。
如你指定:
- CMD [“/bin/echo”,“this is a echo test”]
build 后运行(假设镜像名为 ec):
- docker run ec
就会输出: this is a echo test
是不是感觉很像开机启动项,你可以暂时这样理解。
注意点:
docker run 命令如果指定了参数会把 CMD 里的参数覆盖:(这里说明一下,如:docker run -it Ubuntu /bin/bash 命令的参数是指 /bin/bash 而非 -it ,-it 只是 docker 的参数,而不是容器的参数,以下所说参数均如此。)
同样是上面的 ec 镜像启动:
docker run ec /bin/bash
就 不会 输出:this is a echo test,因为 CMD 命令被”/bin/bash”覆盖了。
ENTRYPOINT
字面意思是进入点,而它的功能也恰如其意。
An ENTRYPOINT allows you to configure a container that will run as an executable. 它可以让你的容器功能表现得像一个可执行程序一样。
容器功能表现得像一个可执行程序一样,这是什么意思呢?
直接给个例子好说话:
例子一:
使用下面的 ENTRYPOINT 构造镜像:
- ENTRYPOINT [“/bin/echo”]
那么 docker build 出来的镜像以后的容器功能就像一个 /bin/echo 程序:
比如我 build 出来的镜像名称叫 imageecho,那么我可以这样用它:
- docker run -it imageecho“this is a test”
这里就会输出”this is a test”这串字符,而这个 imageecho 镜像对应的容器表现出来的功能就像一个 echo 程序一样。你添加的参数“this is a test”会添加到 ENTRYPOINT 后面,就成了这样 /bin/echo“this is a test”。现在你应该明白进入点的意思了吧。
例子二:
ENTRYPOINT [“/bin/cat”]
构造出来的镜像你可以这样运行(假设名为 st):
- docker run -it st /etc/fstab
这样相当:/bin/cat /etc/fstab 这个命令的作用。运行之后就输出 /etc/fstab 里的内容。
ENTRYPOINT 有两种写法:
写法一:
- ENTRYPOINT [“executable”, “param1”, “param2”] (the preferred exec form)
写法二:
- ENTRYPOINT command param1 param2 (shell form)
你也可以在 docker run 命令时使用–entrypoint 指定(但是只能用写法一)。
下面是我把 ENTRYPOINT 设为 [“/bin/sh -c”] 时候运行的情况:
- linux-oj9e:/home/lfly/project/docker # docker run -it t2 /bin/bash
- root@4c8549e7ce3e:/# ps
- PID TTY TIME CMD
- 1 ? 00:00:00 sh
- 9 ? 00:00:00 bash
- 19 ? 00:00:00 ps
可以看到 PID 为 1 的进程运行的是 sh,而 bash 只是 sh 的一个子进程,/bin/bash 只是作为 /bin/sh - c 后面的参数。
CMD 可以为 ENTRYPOINT 提供参数,ENTRYPOINT 本身也可以包含参数,但是你可以把那些可能需要变动的参数写到 CMD 里而把那些不需要变动的参数写到 ENTRYPOINT 里面例如:
- FROM ubuntu:14.10
- ENTRYPOINT [“top”, “-b”]
- CMD [“-c”]
把可能需要变动的参数写到 CMD 里面。然后你可以在 docker run 里指定参数,这样 CMD 里的参数 (这里是 -c) 就会被覆盖掉而 ENTRYPOINT 里的不被覆盖。
注意点1:
ENTRYPOINT 有两种写法,第二种 (shell form) 会屏蔽掉 docker run 时后面加的命令和 CMD 里的参数。
注意点2:
网上有资料说 ENTRYPOINT 的默认值是[”/bin/sh -c”],但是笔者在试验的时候得到的结果并不是这样的。
笔者使用 ENTRYPOINT [“/bin/sh -c”] 指令构造一个以 /bin/sh - c 为进入点的镜像,命名为 sh,然后我可以这样运行:
- docker run -it sh“while(ture) do echo loop; done”
运行结果就是无限输出 loop。但如果直接运行一个 ubuntu:14.10 镜像,情况不是这样的:
- docker run -it ubuntu:14.10“while(ture) do echo loop; done”
得到这样的错误:
- linux-oj9e:/home/lfly # docker run -it ubuntu:14.10“while(true) do echo this; done”2014/11/16 18:07:53 Error response from daemon: Cannot start container 4bfe9c6faeec3ed465788a201a2f386cb1af35aba197dbc78b87c0d5dda1f88e: exec:“while(true) do echo this; done”: executable file not found in $PATH
可以猜想默认情况下 ENTRYPOINT 并不是[“/bin/sh -c”]。
而且直接运行 ubuntu:14.10 列出程序也可以看到 PID 为 1 的程序并不是 sh。所以更否定了网友的说法,ENTRYPOINT 并不默认为[“/bin/sh -c”]。
更多 Docker 相关教程见以下内容:
Docker 安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm
Ubuntu 14.04 安装 Docker http://www.linuxidc.com/linux/2014-08/105656.htm
Ubuntu 使用 VNC 运行基于 Docker 的桌面系统 http://www.linuxidc.com/Linux/2015-08/121170.htm
阿里云 CentOS 6.5 模板上安装 Docker http://www.linuxidc.com/Linux/2014-11/109107.htm
Ubuntu 15.04 下安装 Docker http://www.linuxidc.com/Linux/2015-07/120444.htm
在 Ubuntu Trusty 14.04 (LTS) (64-bit)安装 Docker http://www.linuxidc.com/Linux/2014-10/108184.htm
在 Ubuntu 15.04 上如何安装 Docker 及基本用法 http://www.linuxidc.com/Linux/2015-09/122885.htm
Ubuntu 16.04 上 Docker 使用手记 http://www.linuxidc.com/Linux/2016-12/138490.htm
Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里
本文永久更新链���地址:http://www.linuxidc.com/Linux/2017-03/141819.htm