4

docker 容器的一些概念辨析

 2 years ago
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.
neoserver,ios ssh client

本篇的主要内容是为了澄清 docker 容器的一些容易混淆的概念,主要分两部分, 一是容器端口的publishexpose,二是 Dockerfile 中ENTRYPOINTCMD的区分。

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 中,我们可以指定默认的ENTRYPOINTCMD。比如我们执行docker run -it ubuntu的 时候,效果和docker run -it ubuntu bash是一样的,因为 ubuntu 的 Dockerfile 里指定了 CMDbash.

二者的分离主要也是应用在 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"]。 注意事项:

  1. exec 形式是以 json 数组的形式来解析的,所以各参数必须用双引号"",不能用单引号''
  2. 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 中指定了执行程序),但是不能传递信号。

## 参考链接


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK