docker入门教程(三)Docker 镜像

ps:镜像是Docker容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。

1.11 hello-world ------- 最小的镜像

hello-world 是 Docker 官方提供的一个镜像,通常用来验证Docker是否安装成功

通常来说,我们希望镜像能提供一个基本的操作系统环境,用户可以根据需要安装和配置软件。

这样的镜像我们称作 base 镜像。

1.12 base镜像

base 镜像有两层含义:(1)不依赖其它镜像,从secrch 构建;

                                     (2)其他镜像可以以之为基础进行扩展;

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

我们以 CentOS 为例考察 base 镜像包含哪些内容。

下载镜像

docker pull centos 

查看镜像信息:如图

镜像大小不到200MB.

平时我们安装一个CentOS至少几个GB,怎么才200MB! 下面我们来解释这个问题

Linux操作系统由内核空间和用户空间组成,如图

1.rootfs

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

用户空间的文件系统是 rootfs,包含我们熟悉的 /dev ,proc,/bin 等目录。

对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。

而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令,工具和程序库就可以,

2.base 镜像提供的是最小安装的 Linux 发行版

CentOS 镜像的 Dockerfile 的内容如下

FROM scratch

ADD centos-7docker.tar.xz /

CMD ["/bin/bash"]

第二行 ADD 指令添加到镜像的tar包就是CentOS 7 的rootfs。在制作镜像时,这个tar包会自动解压到 / 目录下,生成/dev,/proc,/bin 等目录

3.支持运行多种 Linux OS

不同 Linux 发行版本的区别主要就是 rootfs。

 比如 Ubuntu 14.04 使用 upstart 管理服务,apt 管理软件包;而 Centos 7 使用 systemd 和 yum。这些都是用户空间上的区别,Linux kernel 差别不大。

所以 Docker 可以同时支持多种 Linux 镜像,模拟初多种操作系统环境,如下图所示

上图 Debian 和 BusyBox(一种嵌入式 Linux)上层提供各自的 rootfs,底层共用 Docker Host 的 Kernel。

这里需要说明的是:

1)base镜像只是在用户空间与发行版一致,Kernel 版本与发行版本是不同的。
例如 CentOS 7 使用3.x.x的kernel,如果Docker Host 是 Ubuntu 16.04,那么在 CentOS容器中使用的实际上是Host 4.x.x的kernel
root@ubuntu: ~# uname -r
4.4.0-31-generic    ①
root@ubuntu: ~#
root@ubuntu: ~# docker run -it centos    ②
[root@231ad31 /]# cat /etc/redhat-release 
CentOS Linux release 7.5.1804 (Core)    ③
 [root@231ad31 /]# uname -r
4.4.0-31-generic

①.Host Kernel 4.4.0-31
②.启动并进入容器。
③.验证容器是 CentOS 7。
④.容器的 Kernel 版本与 Host 一致
(2)容器只能使用 Host 的 Kernel,并且不能修改
ps:所有容器都共用 host 的 Kernel,在容器中没办法对nKernel 升级

3.1.3 镜像的分层结构

Docker 支持通过扩展现有镜像,创建新的镜像。

实际上,Docker Hub中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。比如我们现在构建一个新的镜像,Dockerfile如下

FROM debian    ①
RUN apt-get install emacs    ②
RUN apt-get install apache2    ③
CMD ["/bin/bash"]    ④
①.新镜像不再是从 scratch 开始,而是直接在 Debian base 镜像上构建。
②.安装 emacs
③.安装 apache2.
④.容器启动时运行 bash

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

 为什么Docker镜像要采用这种分成结构呢?

 最大的一个好处就是:共享资源。

 比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只加载一份 base 镜像,就可以为所有容器服务了,而且镜像的每一层都可以被共享

 如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如/etc 下的文件,这是其他容器的 /etc 是否也会被篡改?

 答案是不会!!! 

 修改会被限制在单个容器内

 容器的 Copy-on-Write特性:

 可写的容器层

当启动容器时,一个新的可写层被加载带镜像的顶部。

这一层通常被称作"容器层","容器层" 之下的都叫 “镜像层” 如下图:

所有对容器的改动,无论添加,删除,还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

下面我们深入讨论容器层的细节。

镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统
(1.) 添加文件。在容器中创建文件时,新文件被添加到容器层中。
(2.) 读取文件。在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存
(3.) 修改文件。在容器中修改已存在的文件时,Docker 会从上往下依次在各个镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之
(4.) 删除文件。在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-write。可见,容器层保存的时镜像变化的部分,不会对镜像本身进行任何修改
这样就解释了之前的问题,容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享
原文地址:https://www.cnblogs.com/mclzy/p/9214165.html