3

【Docker 系列】docker 学习 四,镜像相关原理

 2 years ago
source link: https://segmentfault.com/a/1190000040953145
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【Docker 系列】docker 学习 四,镜像相关原理

镜像是什么?

镜像是一种轻量级的,可执行的独立的软件包。

镜像用来打包软件的运行环境和基于运行环境开发的软件,它包含运行某些软件所需要的所有内容,例如:代码,运行时库,环境变量和配置文件等等

所有的应用,可以直接打包 docker 镜像,一键部署,一键运行

得到镜像方式有哪些?

  • 直接拷贝其他 docker 镜像
  • 自己制作一个镜像 DockerFile
  • 从远程仓库下载,如 dockerhub

Docker 镜像的加载原理

UnionFS

UnionFS,是联合文件系统,还记的我们 docker 学习二 里面安装 redis 的时候,出现的分层下载吗

这就是联合文件系统

UnionFS 联合文件系统,是一种分层,轻量级并且高性能的文件系统

它支持对文件系统的修改作为一次提交来一层一层的叠加,同时可以将不同目录挂载到一个虚拟文件系统下

UnionFS 联合文件系统是 Docker 镜像的基础,镜像还可以通过分层来继承,基于基础的镜像,我们可以制作成各种应用镜像

特性:

联合文件系统一次同时加载多个文件系统,联合加载会把各层的文件系统叠加起来,最终的文件系统会包含所有底层的文件和目录

Docker 的镜像加载原理是什么呢?

图片来源于网络

Docker 的镜像是有一层一层的文件系统组成的,这个层级的文件系统就叫做联合文件系统,一般底下的层都是共用的

一般系统启动,是一个加载的过程,这个过程是 bootloader 引导加载 kernel,linux 操作系统刚启动的时候还会加载 bootfs 文件系统,而咱们的 Docker 镜像最底层就是 bootfs

bootfs

boot file system 是一个文件系统,主要是包含 bootloader 和 kernel

当 boot 加载完毕之后,整个内核都在运行正在内存中的,此时内存的使用权已经由 bootfs 交接给内核,这个时候系统会将 bootfs 卸载掉

rootfs

在来说一下 rootfs,root file system,根文件系统,它是在 bootfs 之上的,就是包含了,linux 操作系统中的 /dev ,/proc,/bin,/etc 等目录和文件

例如我们知道的 rootfs 有 centos,ubuntu等等

我们来下载一个 redis 看看效果

Docker 是按照层级进行下载,之前下载过的层级就不会再次下载了,我们可以通过 docker inspect 查看 redis 的细节

# docker inspect redis:latest
...
"RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4",
                "sha256:dd1ebb1f5319785e34838c7332a71e5255bda9ccf61d2a0bf3bff3d2c3f4cdb4",
                "sha256:11f99184504048b93dc2bdabf1999d6bc7d9d9ded54d15a5f09e36d8c571c32d",
                "sha256:e461360755916af80821289b1cbc503692cf63e4e93f09b35784d9f7a819f7f2",
                "sha256:45f6df6342536d948b07e9df6ad231bf17a73e5861a84fc3c9ee8a59f73d0f9f",
                "sha256:262de04acb7e0165281132c876c0636c358963aa3e0b99e7fbeb8aba08c06935"
            ]
        },
...

如上结果我们可以看到,redis 的层级与我们 pull 拉取镜像时候的层级一致

那么Docker 为什么要采用分层下载呢?

主要是为了共享资源

例如我们的多个镜像都是从基础镜像构建而来,那么宿主机只需要在机器上保留一份基础镜像即可,并且内存中也只需要加载一份基础镜像,就可以为所有需要的容器服务,而且镜像的每一层也都是可以共享的

我们可以这样来理解:

所有的 Docker 镜像都来源于基础镜像,我们增加或修改镜像内容的时候,就会在当前镜像层上面,新建一个镜像层,这就例如 windows 里面的一个安全补丁

如上面图例:

我们在镜像的第一层,放置 file1,file2,镜像的第二层放置 file3,file4,镜像的第三层放置file3.1 (file3.1 是 file3 的一个新版本)

那么,我们在打包镜像的时候,就会合并出 一个镜像里面,有 4 个文件,此处也就是 4个 layer

当我们下载这个最终合并的镜像时,就会一次下载上述的 4 个layer

Docker 镜像的特点:

Docker 镜像默认都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部

上面说的这一层就是咱们的容器层,容器层下面是镜像层,如下图所示

如何提交咱们的镜像

Docker 提交原理和命令与 Git 类似

docker commit

提交当前容器,成为一个新的版本

我们一般会这样使用

docker commit -m="描述信息" -a="作者" 容器ID 目标镜像名:[TAG]

举个例子:

咱们自己修改一下 nginx 镜像,作为我们自己的镜像来使用

启动 nginx ,设置端口映射为 -p 8888:80

docker run -d -p 8888:80 nginx

以交互方式进入 nginx

# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                  NAMES
30841a3a26cb   nginx     "/docker-entrypoint.…"   4 seconds ago   Up 2 seconds   0.0.0.0:8888->80/tcp   strange_hugle

# docker exec -it 30841a3a26cb /bin/bash

进入到nginx 的html 目录,将index.html 文件替换掉,,nginx重新加载配置

#cd /usr/share/nginx/html
#ls
50x.html  index.html
#mv index.html index.html.bak
#mv 50x.html index.html
#/usr/sbin/nginx -s reload

这个时候,我们访问一个服务器的 8888 端口,查看效果(我们将正常的 index.html 页面,换成了一个显示错误的页面)

如上图,果然更换成功了

咱们来进行一下 commit

docker commit -a="xiaomotong" -m="modify index.html" 30841a3a26cb nginx01:1.0

~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                  NAMES
30841a3a26cb   nginx     "/docker-entrypoint.…"   10 minutes ago   Up 10 minutes   0.0.0.0:8888->80/tcp   strange_hugle
root@iZuf66y3tuzn4wp3h02t7pZ:~# docker commit -a="xiaomotong" -m="modify index.html" 30841a3a26cb nginx01:1.0
sha256:1d072fa616573ba67a103925c6114e40171eb1d14ca573f146a28b8c51e5fdff
root@iZuf66y3tuzn4wp3h02t7pZ:~# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
nginx01               1.0       1d072fa61657   3 seconds ago   133MB
ubuntu                latest    1318b700e415   7 days ago      72.8MB
redis                 latest    aa4d65e670d6   11 days ago     105MB
nginx                 latest    08b152afcfae   12 days ago     133MB
portainer/portainer   latest    580c0e4e98b0   4 months ago    79.1MB

如果我们想要保存自己的容器当前状态,咱们就可以通过 commit 来提交,获得一个想要的镜像,这就有点像使用虚拟机打快照一样

参考资料:

docker docs

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是小魔童哪吒,欢迎点赞关注收藏,下次见~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK