Docker 镜像的制作和使用

镜像 Layer(层)

镜像里的内容是按「层」来组织的,「层」可以复用,一个完整的镜像也可以看做是一个「层」。多个「层」叠加在一起就形成了一个新的镜像,这个镜像也可以作为别的镜像的基础「层」进行更加复杂的镜像构建。下图展示了一个镜像的内部结构。

Docker 镜像的制作和使用

这个目标镜像使用 Debian 镜像作为基础镜像开始构建,也就是说 Debian 镜像是目标镜像的第一「层」;往上的两层分别使用了 ADD 指令将 emacs 和 apache 添加到了目标镜像中,每一个 ADD 指令都将产生新的一个「层」,最后这个目标镜像就是一个拥有三「层」的镜像。每新增一「层」时,将要生成的这一「层」镜像都会默认使用上一步构建出的「层」作为自己的基础镜像,上图中的箭头表示的就是这种引用关系。

所以,「层」和「镜像」是等价的,当这一「层」之上没有其他「层」时,我们就可以将这一「层」及其下面的所有「层」合起来称作一个「镜像」。如果这一「层」只是在构建镜像过程中生成的一个「中间层」,即这一「层」不会被用来启动容器,那么就可以称作「层」。总的来说,能用来启动容器的就称作「镜像」,其他都称作「层」。

制作镜像

制作镜像的过程和在操作系统上安装软件的过程几乎是完全一样的,唯一的区别是制作镜像需要使用 Dockerfile 文件来编写要执行的操作。请注意,Dockerfile 里的所有指令,除了 CMD 和 ENTRYPOINT,都是给 Docker 引擎执行的,目的是制作出目标镜像,这些指令不是启动容器的时候执行的。

下面的例子将一步步演示从 0 开始制作一个在 CentOS7.2 操作系统上安装了 openjdk 和 nginx 并运行一个 Java 应用程序的镜像,这个过程同时也将体现镜像分层复用的思想。

镜像分层复用思想

Dockerfile 中的每个指令都会生成一个「层」,最终的目标镜像就是由多个「层」组成的。如果制作 B 镜像的 Dockerfile 中存在某个指令与制作 A 镜像的 Dockerfile 中的某个指令完全一致,那么制作 B 镜像时就会复用制作 A 镜像时生成的「中间层」,而不会再去创建一个新的「层」,这就是「镜像分层复用」思想。

第一步,制作一个支持中文的 CentOS 镜像

官方为我们提供了 Linux 各种发行版的镜像,我们日常的所有镜像构建都是基于这些镜像来完成的。由于官方的 CentOS 镜像并不支持中文字符集,所以我们需要先制作一个支持中文的镜像出来

编写 Dockerfile FROM centos:7.2.1511 RUN yum install -y telnet kde-l10n-Chinese net-tools vim inetutils-ping unzip \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 \ && yum clean all ENV LC_ALL "zh_CN.UTF-8" CMD ["/bin/bash"]

FROM 指令表示我们从官方提供的 CentOS 镜像开始构建我们自己的镜像。centos 是镜像的名称,7.2.1511 是镜像的版本。

RUN 指令表示在构建镜像时我们要执行的 shell 命令。之前的 FROM 指令相当于给了我们一个干净的操作系统,我们在这个系统上要执行的各种操作,如安装软件、创建目录等就都要书写在这个 RUN 指令之后。理论上你可以对每一个要执行的 shell 命令都使用一个 RUN 指令,比如我们将上面的 RUN 指令改写为下面的样子:

RUN yum install -y telnet kde-l10n-Chinese net-tools vim inetutils-ping unzip RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 RUN yum clean all

这样编写出来的 Dockerfile 文件是没有任何问题的,镜像最终也能够制作成功,但是这并不切合镜像分层复用的思想,因为我们几乎不会用到上面单个 RUN 指令生成的「中间层」。这样编写指令只会增加磁盘空间的占用,也让 Dockerfile 变得非常臃肿。

需要特别注意的是,如果 RUN 指令中有安装软件的操作,那就一定要在 RUN 指令的最后清除掉软件仓库的缓存,这样可以有效的瘦身镜像。

ENV 指令表示在构建镜像时要在操作系统中设置的环境变量。这个指令每次只能设置一个环境变量,如果需要设置多个环境变量,则需要编写多个 ENV 指令。

CMD 指令表示的是容器启动时要执行的操作,通常会设置为应用程序的启动脚本,这个指令一定是出现在 Dockerfile 的最后。被指定的操作一定是能够挂起一个进程的操作,否则容器启动并执行完这个操作后就会退出。

构建镜像

构建镜像时需要告诉 Docker 引擎 Dockerfile 的位置、镜像的名称和构建位置三个信息,下面是一个简单的镜像构建命令:

docker build -t myorg/centos:7.2 .

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfxdd.html