作者:CC_橙_CC | 来源:互联网 | 2023-05-19 14:03
ps:镜像是Docker容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。1.11hello-world-------最小的镜像hello-world是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。可见,容器层保存的时镜像变化的部分,不会对镜像本身进行任何修改
这样就解释了之前的问题,容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享