Docker镜像详解
什么是镜像
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的所有内容,包括代码,运行时(一个程序在运行或者在被执行的依赖)、库,环境变量和配置文件。
所有应用,直接打包docker,可以直接运行
Docker镜像加载原理
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统是UnionFS联合文件系统。
Docker的镜像实际由一层一层的文件系统组成:
- bootfs(boot file system)主要包含bootloader和kernel。bootloader主要是引导加载kernel,完成后整个内核就都在内存中了。此时内存的使用权已由bootfs转交给内核,系统卸载bootfs。可以被不同的Linux发行版公用。
- rootfs(root file system),包含典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同操作系统发行版(Ubuntu,Centos等)。因为底层直接用Host的kernel,rootfs只包含最基本的命令,工具和程序就可以了。
- 分层理解
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的容器层。
容器在启动时会在镜像最外层上建立一层可读写的容器层(R/W),而镜像层是只读的(R/O)。
rootfs (root file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc, /bin, /etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。Rootfs(根文件系统),在引导之上。包含的就是典型linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。Rootfs就是各种不同的操作系统发行版,比如Ubuntu,CentOS等等。
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M ?
对于一个精简的oS, rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别,因此不同的发行版可以公用bootfs。
分层理解
我们去下载一个镜像,注意下载日志,可以发现是分层进行下载的
思考∶为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
:::tips
查看镜像分层的方式可以通过docker image inspect命令!
:::
[root@localhost ~]# docker image inspect redis:latest
[
{
"Id": "sha256:7614ae9453d1d87e740a2056257a6de7135c84037c367e1fffa92ae922784631",
"RepoTags": [
"redis:latest"
],
"RepoDigests": [
"redis@sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339"
],
"Parent": "",
"Comment": "",
"Created": "2021-12-21T12:42:49.755107412Z",
"Container": "13d25f53410417c5220c8dfe8bd49f06abdbcd69faa62a9b877de02464bb04a3",
"ContainerConfig": {
"Hostname": "13d25f534104",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"REDIS_VERSION=6.2.6",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.6.tar.gz",
"REDIS_DOWNLOAD_SHA=5b2b8b7a50111ef395bf1c1d5be11e6e167ac018125055daa8b5c2317ae131ab"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"redis-server\"]"
],
"Image": "sha256:e093f59d716c95cfce82c676f099b960cc700432ab531388fcedf79932fc81ec",
"Volumes": {
"/data": {}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"REDIS_VERSION=6.2.6",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.6.tar.gz",
"REDIS_DOWNLOAD_SHA=5b2b8b7a50111ef395bf1c1d5be11e6e167ac018125055daa8b5c2317ae131ab"
],
"Cmd": [
"redis-server"
],
"Image": "sha256:e093f59d716c95cfce82c676f099b960cc700432ab531388fcedf79932fc81ec",
"Volumes": {
"/data": {}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 112691373,
"VirtualSize": 112691373,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/e9108002980c92a086707dd3fdaf92585a359803f62463eec03d44d552432e9e/diff:/var/lib/docker/overlay2/ee41879c2adad89d8e0847e4186d01a39dbaa48c3f71fcd725ca55278ee84c14/diff:/var/lib/docker/overlay2/d48921882961deb5ec301f7877e5a529f094475c25a044240f35957b013e2b9b/diff:/var/lib/docker/overlay2/b699114ebaf4efdba2086f24f289bbd2223f6159811f6d2ddf00f0184030883e/diff:/var/lib/docker/overlay2/3186fbc839e6e7d6ecc565b3378d22494f1ec8ee9454f8335a82883dbf21e450/diff",
"MergedDir": "/var/lib/docker/overlay2/67146a76f119a87a206599fb753914929ecfd2093f19fa08d8893fbf7c0ee298/merged",
"UpperDir": "/var/lib/docker/overlay2/67146a76f119a87a206599fb753914929ecfd2093f19fa08d8893fbf7c0ee298/diff",
"WorkDir": "/var/lib/docker/overlay2/67146a76f119a87a206599fb753914929ecfd2093f19fa08d8893fbf7c0ee298/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:9b24afeb7c2f21e50a686ead025823cd2c6e9730c013ca77ad5f115c079b57cb",
"sha256:4b8e2801e0f956a4220c32e2c8b0a590e6f9bd2420ec65453685246b82766ea1",
"sha256:529cdb636f61e95ab91a62a51526a84fd7314d6aab0d414040796150b4522372",
"sha256:9975392591f2777d6bf4d9919ad1b2c9afa12f9a9b4d260f45025ec3cc9b18ed",
"sha256:8e5669d8329116b8444b9bbb1663dda568ede12d3dbcce950199b582f6e94952"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。、
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1].下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点:
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
commit镜像
docker commit 提交镜像成为一个新的副本
#原理与git相似
docker commit -m ="提交的一些信息" -a="作者" 容器id 镜像名:[tag]
实战测试:
#启动一个默认的tomcat
#发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认 webapps下面是没有文件的!
#拷贝进去了基本的文件
#1.复制文件
[root@localhost ~]# docker exec -it c488a6848f7d /bin/bash
root@c488a6848f7d:/usr/local/tomcat# cd webapps
root@c488a6848f7d:/usr/local/tomcat/webapps# ls
root@c488a6848f7d:/usr/local/tomcat/webapps# cd ../
root@c488a6848f7d:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@c488a6848f7d:/usr/local/tomcat# cd webapps
root@c488a6848f7d:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
#2.查看运行状态
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c488a6848f7d fb5657adc892 "catalina.sh run" 3 hours ago Up 3 hours 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp tender_zhukovsky
#3.进行镜像提交
[root@localhost ~]# docker commit -a=““"utoujun" -m="add webapps app" c488a6848f7d tomcat02:1.0
sha256:855f0e3d5375642f9a80d3b59e903c7e14984490372a41ae46750192996fa616
#4、将我们操作过的容器通过commit提交为一个镜像!
我们以后就使用我们修改过的镜像即可,
这就是我们自己的一个修改的镜像
标签:false,详解,usr,镜像,docker,sha256,root From: https://www.cnblogs.com/yutoujun/p/16927531.html如果你想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,就好比我们以前学习VM时候,快照!