Docker 镜像原理(五)
这篇文章介绍了Docker镜像的原理和操作案例。镜像是一种轻量级、可执行的独立软件包,包含容器运行所需的全部内容。镜像是由一层一层的文件系统组成,使用UnionFS实现分层和叠加。镜像的每一层都是只读的,基于基础镜像可制作多种具体的应用镜像。 Docker 的镜像实际上由一个主文件系统和多个只读文件系统叠加而成,最底层是bootfs,包含bootloader和内核。构建容器时会在镜像的基础上添加一个可写层用来保存容器运行时的修改。
Docker 镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。
以我们的 docker pull tomcat
为例,在下载的过程中我们可以看到 docker 的镜像好像是在一层一层的在下载。
jsx[root@localhost ~]# docker pull tomcat
Using default tag: latest
latest: Pulling from library/tomcat
0e29546d541c: Pull complete
9b829c73b52b: Pull complete
cb5b7ae36172: Pull complete
6494e4811622: Pull complete
668f6fcc5fa5: Pull complete
dc120c3e0290: Pull complete
8f7c0eebb7b1: Pull complete
77b694f83996: Pull complete
0f611256ec3a: Pull complete
4f25def12f23: Pull complete
Digest: sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest
镜像包含着容器运行时所需要的代码以及其它组件,它是一种分层结构,每一层都是只读的(read-only layers)。构建镜像时,会一层一层构建,前一层是后一层的基础。镜像的这种分层存储结构很适合镜像的复用以及定制。
构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。
Docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
[quote color=“info”] 对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。 [/quote]
特点:共享资源。比如,有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层称为"容器层",“容器层"之下为"镜像层”。
我们有2种方法查看镜像:
docker inspect
:获取镜像的元数据docker history
:查看镜像的构建历史理论上,一个容器的镜像,最多可以有127层,怎么查看镜像的层数?
通过 docker Inspect
命令,寻找 RootFS
代码片段,在 Layers
中,有多少行 (sha256)
就代表镜像有多少层。
bashdocker inspect nginx #根据镜像nginx,查看镜像详细信息
bash"RootFS": {
"Type": "layers",
"Layers": [
"sha256:92770f546e065c4942829b1f0d7d1f02c2eb1e6acf0d1bc08ef0bf6be4972839",
"sha256:8ae474e0cc8f5a81405b04143604f78bfac4756c523e276a36921a8c4da36567",
"sha256:f5525891d9e9b43a95b4aa1f79405087922489eb300864a2683262aae0fa5b3a",
"sha256:66283570f41bca3619443d121a79e810b8a72849b5329319993e538d563b3e2f",
"sha256:c2d3ab485d1b375fdd309458d69d93f8eb9aba8472e928efa32d9e5eda631440",
"sha256:cddc309885a283a35ef142af78bc6f2e9c9db10e1981c4ea9cfb2c00b83e68ff",
"sha256:0d0e9c83b6f775d68c7517aabf39ec9123ffca29672e3c3f83c5af7fc6aa242b"
]
},
使用docker history
可以看到镜像的构建历史。
bashdocker history nginx
bashIMAGE CREATED CREATED BY SIZE COMMENT
a6bd71f48f68 12 days ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 12 days ago /bin/sh -c #(nop) STOPSIGNAL SIGQUIT 0B
<missing> 12 days ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 12 days ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B
<missing> 12 days ago /bin/sh -c #(nop) COPY file:9e3b2b63db9f8fc7… 4.62kB
在Dockerfile中一般,每一行的添加ADD、COPY、RUN,或者创建新(配置)文件的命令,都会触发新建一层镜像,这层镜像一般会被称为中间层镜像,中间层镜像存在的意义:加速镜像构建、重复利用资源。
使用 docker commit
提交容器副本使之成为为一个新的镜像,在此示例中,我们使用 ubuntu 镜像为例,原始的默认ubuntu镜像不带vim命令,我们在外网连通的情况下,安装 vim 软件,安装完成后commit为新的ubuntu镜像。
bash# 运行 unbntu 镜像
[root@localhost ~]# docker run -it ubuntu bash
# 配置更新
root@393af6f0b855:/# apt-get update
# 安装 vim
root@393af6f0b855:/# apt-get install -y vim
# 验证
root@393af6f0b855:/# vim a.txt
root@393af6f0b855:/# cat a.txt
aaa
# 提交容器副本使之成为一个新Ubuntu镜像
[root@localhost ~]# docker commit -m="vim cmd add ok" -a="whb" 393af6f0b855 myubuntu:v1
# 查看镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myubuntu v1 a7a511fae0fb 9 seconds ago 178MB
bash# commit 语法
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的镜像名称:[tag]
本文作者:LiuXueChao
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!