docker 容器的一些概念辨析
source link: https://yanhang.me/post/2015-04-16-some-concepts-of-docker-containers/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
本篇的主要内容是为了澄清 docker 容器的一些容易混淆的概念,主要分两部分,
一是容器端口的publish
和expose
,二是 Dockerfile 中ENTRYPOINT
和CMD
的区分。
Expose or Publish
expose
的作用是为了容器间通信,也就是说 expose 的端口只能被其他容器访问,但是
不能被 docker 之外访问,而publish
的端口即可用于容器间通信也可被外界访问。所以从
逻辑上来说,publish
包含了expose
。
有这样的区分主要是为了可移植性。我们知道在Dockerfile
文件中只有Expose
命令,
expose
暴露的端口只能用于容器间通信,不会跟主机上的端口冲突。如果在
Dockerfile
中加入了publish
,在其他的机器上构建时就有可能导致端口冲突。
在命令行里使用这两个参数时,二者是可以混用的,不会冲突。同时指定--expose
和
--publish
与单独使用--publish
的效果一样。
ENTRYPOINT or CMD
Docker 提供了一个默认的ENTRYPOINT
:/bin/sh -c
,但是没有默认的CMD
。比如当我们
在命令行里执行docker run -it ubuntu bash
的时候,entrypoint 就是/bin/sh -c
,
command 就是bash
。
在命令行里,所有镜像名字之后的参数都是作为 command 传给了 entrypoint。在Dockerfile
中,我们可以指定默认的ENTRYPOINT
和CMD
。比如我们执行docker run -it ubuntu
的
时候,效果和docker run -it ubuntu bash
是一样的,因为 ubuntu 的 Dockerfile 里指定了
CMD
为bash
.
二者的分离主要也是应用在 Dockerfile 中,通过灵活的设置,我们可以做出来一些有趣的,
很方便使用的镜像。比如将ENTRYPOINT
设为[/bin/cat]
,那么在执行docker run catimg /etc/password
的时候就相当于在执行/bin/cat /etc/password
,整个镜像此时变
成了一个二进制程序。这个例子可能显得有点无聊,但是既然任意程序都可以用做
ENTRYPOINT
,自然是只有想不到,没有做不到了。如果将一个 redis 镜像的ENTRYPOINT
设
为["redis", "-H", "something", "-u", "toto"]
,那么在执行docker run redisimg get key
就相当于docker run redisimg redis -H something -u toto get key
,这就是
一个简单明了的 redis 客户端,也不用输那么多参数了。
Dockerfile 中与此相关的命令还有一个RUN
,相关细节较为琐碎,下面将详细叙述:
RUN
用来在上一层 layer 的基础上执行一些系统命令并且创建新的一层,可以说是
Dockerfile 中最为常见的命令了,主要有两种形式
RUN <command>
通过/bin/sh -c
执行RUN ["executable", "param1", "param2"]
(exec 形式)
exec 形式可以避免 shell 对参数的一些处理并且可以用在一些没有/bin/sh
的基本镜像上,
如果想使用别的 shell,也可以使用此种方式,比如RUN ["/bin/bash", "-c", "echo hello"]
。
注意事项:
- exec 形式是以 json 数组的形式来解析的,所以各参数必须用双引号
""
,不能用单引号''
。 - exec 形式下如果不明确制定是不会调用 shell 的,也就意味着一些环境变量是无法解析的,
比如RUN [ "echo", "$HOME" ]
,如果需要必须自己明确指定所用的 shell
CMD
主要是为容器提供默认的运行程序,有三种形式:
CMD ["executable","param1","param2"]
(exec 形式)CMD ["param1","param2"]
(将参数传给ENTRYPOINT
)CMD command param1 param2
(shell 形式,/bin/sh -c
执行)
一个 Dockerfile 中只能有一个CMD
,如果指定了多个,只有最后一个起作用。运行时的参
数会覆盖 Dockerfile 中CMD
。
注意事项可参考RUN
的注意事项
ENTRYPOINT
ENTRYPOINT
有两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
(exec 形式)ENTRYPOINT command param1 param2
(shell 形式)
类似于CMD
,如果指定了多个ENTRYPOINT
,只有最后一个起作用。docker run --entrypoint
可覆盖 Dockerfile 中的设置。
exec 形式是最常用的,shell 形式会阻止任何CMD
或者run
的参数的执行(因为已经在
ENTRYPOINT 中指定了执行程序),但是不能传递信号。
## 参考链接
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK