镜像是 Docker 容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。那还是从hello-world开始了解镜像吧。hello-world 的 Dockerfile 内容如下:

  1. FROM scratch
  2. # 将文件“hello”复制到镜像的根目录。
  3. COPY hello /
  4. # 容器启动时,执行 /hello
  5. CMD ["/hello"]

镜像 hello-world 中就只有一个可执行文件 “/ hello”,就是打印“Hello from Docker!” 的信息,/hello 就是文件系统的全部内容了。

hello-world 虽然是一个完整的镜像,但它并没有什么实际用途,一般都是测试是否安装成功。通常来说,镜像能提供一个基本的操作系统环境, 我们可以根据需要安装和配置软件。这样的镜像也就是 base 镜像。

一、BASE镜像

能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等。

  1. docker images centos

Docker - 镜像 - 图1

查看镜像信息,centos的镜像大小才202MB!而我们平常采用普通的方式安装centos,它的大小不可能只有200多MB的。那么Docker是怎么实现这个操作的呢? 在回答这个问题前,我们需要明确Linux 操作系统由内核空间和用户空间组成。所以Docker用的是这个思路:

内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。

用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。

二、Dockerfile

Dockerfile 是一个文本文件,记录了镜像构建的所有步骤。比如说想要在centos镜像上构建一个安装vim软件的新的镜像。
先到/root目录下面,新增一个Dockerfile文件,内容如下:

  1. FROM centos
  2. RUN yum update -y && yum install -y vim

然后执行构建命令:

  1. docker build -t centos-with-vim .

注意到最后一个”.”,表示构建的context为当前目录。 构建成功后,会自动显示自定义构建镜像的镜像ID。

三、镜像分层

Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中 大部分的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。想刚刚通过Dockerfile构建centos-vim镜像,就是镜像分层的体现。如官网下的这张图片:

Docker - 镜像 - 图2

可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

四、容器层

当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。 只有容器层是可写的,容器层下面的所有镜像层都是只读的。

Docker - 镜像 - 图3

五、查看镜像分层

上面我们所创建的centos-with-vim这个镜像是在基础镜像centos的顶部添加了一层新的镜像而得到。 这一点我们可以通过 docker history 命令验证:
Docker - 镜像 - 图4