镜像是什么

镜像是是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件

Docker 镜像加载原理

UnionFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加同时可以将不同目录挂在到同一个虚拟文件系统下(unite serveral directories into a single virtual filesystem)。Union文件系统时Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制止各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面开起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

Docker镜像加载原理

Docker的镜像世纪上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

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等。

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以。由此可见对不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用。

分层理解

当我们在下载一个镜像时,发现这个镜像时分层下载的。

[root@localhost ~]# docker pull redis

Using default tag: latest

latest: Pulling from library/redis

7d63c13d9b9b: Pull complete 

a2c3b174c5ad: Pull complete 

283a10257b0f: Pull complete 

7a08c63a873a: Pull complete 

0531663a7f55: Pull complete 

9bf50efb265c: Pull complete 

Digest: sha256:a89cb097693dd354de598d279c304a1c73ee550fbfff6d9ee515568e0c749cfe

Status: Downloaded newer image for redis:latest

docker.io/library/redis:latest

Docker为什么要采用这种分层结构?

最大的好处是资源共享,比入有多个镜像都从相同额Base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过`docker image inspect`命令

docker image inspect redis

image-20211021214044071.png

所有的Docker镜像都其实于一个基础镜像,当进行修改或增加新的内容是,就会在当前镜像层之上创建新的镜像层。

例如:基于Ubuntu Linux 16.04创建的一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层。

image-20211021214417869.png

在添加额外的镜像层的同时,镜像使用保持是当前所有镜像的组合。

image-20211021214519374.png

如果在上图的场景中文件5假设为一个APP版本为1.0,然后一个新增的第三层文件7是一个APP,版本为2.0,这种场景下,第三层文件系统的文件7会覆盖掉第二层文件系统的文件5。

在这种情况下,上层镜像中的文件覆盖了底层镜像层中的文件。这样是的文件的更新版本作为新歌新镜像层添加到镜像中。

Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证对外展示为统一的文件系统。

Linux上可以用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,美中存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

Docker在Windows上仅支持Windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW

下图为三层合并后的视图

image-20211021215536178.png

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器之下的叫镜像层。# #

commit镜像

docker commit # 提交容器成为一个新的副本

docker commit -m "对本次提交内的描述" -a "作者信息" 容器id 目标镜像名:[TAG版本号]

测试

# 启动一个tomcat

[root@localhost ~]# docker run -itd -p 8080:8080 tomcat /bin/bash

281ad2d97fb8a2a2620588f0377e9b44dad48f168de8c2c04606701485467fb8

# 进入容器,并查看webapps下文件(官方默认镜像webapps下没有文件,测试页面在webapps.dist下)

[root@localhost ~]# docker exec -it 281ad2d97fb8 /bin/bash

root@281ad2d97fb8:/usr/local/tomcat# ls

BUILDING.txt  CONTRIBUTING.md  LICENSE  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  native-jni-lib  temp  webapps  webapps.dist  work

root@281ad2d97fb8:/usr/local/tomcat# cd webapps

root@281ad2d97fb8:/usr/local/tomcat/webapps# ls

root@281ad2d97fb8:/usr/local/tomcat/webapps# 

# 将webapps.dist下文件复制到webapps下

root@281ad2d97fb8:/usr/local/tomcat# cp -r webapps.dist/* webapps/

root@281ad2d97fb8:/usr/local/tomcat# ls webapps

ROOT  docs  examples  host-manager  manager

root@281ad2d97fb8:/usr/local/tomcat# 

在浏览器中访问创建好的容器,发现可以正常访问了

image-20211023140318455.png

# 将修改过的容器通过commit提交成新的镜像

[root@localhost ~]# docker commit -m="add apps" -a="NowSec" 6bea3991a562 nowsectomcat:1.0

sha256:20b3c05f006f2f477cdea81f7c413011005e9cbf1e36b4f643709bb13131b509

# 查看制作好的镜像

[root@localhost ~]# docker images

REPOSITORY            TAG       IMAGE ID       CREATED          SIZE

nowsectomcat          1.0       20b3c05f006f   45 seconds ago   684MB

tomcat                latest    b0e0b0a92cf9   30 hours ago     680MB

redis                 latest    7faaec683238   10 days ago      113MB

Docker容器数据卷

什么是容器数据卷

当我们使用docker容器的时候,会产生一些数据,这些数据会随着docker容器的关闭而消失,但是有些时候产生的数据我们是希望他能够保存下来的。Docker将应用于运行观景大包成容器发布,我们希望在运行的时候产生的部分数据是可以持久化的,而且容器之间我们希望能够实现数据共享。

> 容器数据卷的特点

1、数据卷可以在入容器之间共享或重用

2、数据卷中的更改可以直接生效

3、数据卷中的更改不会包含在镜像的更新中

4、数据卷的生命周期一直持续到没有容器使用它未知

添加数据卷的方式

1、通过命令行挂载

docker run -it -v 宿主机绝对路径:容器内绝对路径 镜像名

[root@localhost ~]# docker run -itd -v /opt/test:/home centos

cc1255b353d62d0761bedbc29897705985b5811d903c426ee89e79bb6a129640

[root@localhost ~]# docker ps

CONTAINER ID   IMAGE                 COMMAND        CREATED         STATUS         PORTS                                       NAMES

cc1255b353d6   centos                "/bin/bash"    3 seconds ago   Up 2 seconds                                               inspiring_leakey

8c9eb507a4b4   portainer/portainer   "/portainer"   2 days ago      Up 9 hours     0.0.0.0:9000->9000/tcp, :::9000->9000/tcp   focused_ishizaka

[root@localhost ~]# ls /opt/

containerd  test

2、检查挂载

docker inspect 容器id

"Mounts": [

            {

                "Type": "bind",

                "Source": "/opt/test", # 宿主机路径

                "Destination": "/home", # 容器内路径

                "Mode": "",

                "RW": true,

                "Propagation": "rprivate"

            }