一.什么是镜像
镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好行程一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。
二.Docker镜像加载原理
2.1联合文件系统
- Docker 中的文件存储驱动叫做 storage driver。
- Docker 最早支持的stotage driver是 AUFS,它实际上由一层一层的文件系统组成,这种层级的文件系统叫UnionFS。
联合文件系统(UnionFS):Union 文件系统,是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。
Union文件系统是Docker镜像的基础。镜像可以通过分层来进行集成,基于基础镜像可以制作具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
后来出现的docker版本中,除了AUFS,还支持OverlayFS、Btrfs、Device Mapper、VFS、ZFS等storage driver,现在使用OverlayFS
2.2bootfs和rootfs
2.2.1bootfs
bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader主要是引导加载 kernel,Linux刚启动时会加载bootfs文件系统。
在Docker镜像的最底层是引导文件系统bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已经由 bootfs 转交给内核,此时系统也会卸载 bootfs。
2.2.2rootfs
rootfs(root file system),在bootfs之上,包含的就是典型Linux系统中的 /dev
、/proc
、/bin
、/etc
等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu、CentOS等。
docker镜像底层层次:
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接使用Host的Kernel,自己只需要提供rootfs就可以。所以,对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,不同的发行版可以共用bootfs。
三.镜像分层
Docker支持扩展现有镜像,创建新的镜像。新镜像是从base镜像一层一层叠加生成的。
查看镜像分层信息
docker history
截取的nginx的分层
镜像分层的优势
镜像分层的一个最大好处就是共享资源,方便复制迁移,方便复用,镜像的每一层都可以被共享。
四.容器层
Copy On Write(写时复制)
- 写时复制是一种共享和复制文件的策略,可最大程度地提高效率。
- 如果文件或目录位于映像的较低层中,而另一层(包括可写层)需要对其进行读取访问,则它仅使 用现有文件。
- 另一层第一次需要修改文件时(在构建映像或运行容器时),将文件复制到该层并进行修改。 这 样可以将I / O和每个后续层的大小最小化。
容器启动会加载镜像自带配置,但是如果修改容器里面内容,docker会在容器生成一个新的层来储存配置文件,并不会对镜像直接修改。
当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被叫做“容器层”,“容器层”之下都叫做“镜像层”。
所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器层中。,镜像永远不变
只有容器层是可写的,容器层下面的所有镜像层都是只读的。
五.镜像的存储
docker image inspect nginx查看镜像内部信息,截取如下片段,指示了镜像怎么存的
- LowerDir :底层目录; diff(只是存储不同);包含小型linux和装好的软件,只读的
/var/lib/docker/overlay2/67b3802c6bdb5bcdbcccbbe7aed20faa7227d584ab37668a03ff6952e
631f7f2/diff:用户文件;
/var/lib/docker/overlay2/f56920fac9c356227079df41c8f4b056118c210bf4c50bd9bb077bdb4
c7524b4/diff: nginx的启动命令放在这里
/var/lib/docker/overlay2/0e569a134838b8c2040339c4fdb1f3868a7118dd7f4907b40468f5fe6
0f055e5/diff: nginx的配置文件在这里
/var/lib/docker/overlay2/2b51c82933078e19d78b74c248dec38164b90d80c1b42f0fdb1424953
207166e/diff: 小linux系统
我们进入到这个镜像启动的容器,容器的文件系统就是镜像的;
docker ps -s;可以看到这个容器真正用到的文件大小
容器会自己建立层;如果想要改东西,把改的内容复制到容器层即可
docker inspect container查看启动的容器分层信息
"LowerDir":
"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462
c862f1e9a0562de2384dbcinit/diff:/var/lib/docker/overlay2/e3b8bdbb0cfbe5450696c470994b3f99e
8a7942078e2639a788027529c6278f7/diff:/var/lib/docker/overlay2/67b380
2c6bdb5bcdbcccbbe7aed20faa7227d584ab37668a03ff6952e631f7f2/diff:/var
/lib/docker/overlay2/f56920fac9c356227079df41c8f4b056118c210bf4c50bd
9bb077bdb4c7524b4/diff:/var/lib/docker/overlay2/0e569a134838b8c20403
39c4fdb1f3868a7118dd7f4907b40468f5fe60f055e5/diff:/var/lib/docker/ov
erlay2/2b51c82933078e19d78b74c248dec38164b90d80c1b42f0fdb14249532071
66e/diff",
"MergedDir":
"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462
c862f1e9a0562de2384dbc/merged",
"UpperDir": (镜像的上层可以感知变
化)"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d
462c862f1e9a0562de2384dbc/diff",【容器的修改后的文件,保存再宿主机的目录。
容器删除后,那些容器目录随之删除】
"WorkDir":
"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462
c862f1e9a0562de2384dbc/work"
- MergedDir :合并目录;容器最终的完整工作目录全内容都在合并层;数据卷在容器层产生;容器里面有的文件就展示容器里的,容器里没有的就展示镜像里的。
- UpperDir :上层目录; 是lowerdir的上一层,只有这一层是可读可写的,其实就是容器层
- WorkDir :工作目录(临时层),pid;
docker底层的 storage driver完成了以上的目录组织结果;
六.制作发布新镜像
docker commit
提交容器副本使之成为一个新的镜像。
docker 启动一个镜像容器后, 可以在里面执行一些命令操作,然后使用docker commit
将新的这个容器快照生成一个镜像。
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[tag]
5.1本地制作制作Ubuntu镜像
这里以Ubuntu容器安装vim为例:
[root@localhost ~]# docker run -it ubuntu
root@bf9b18b76e62:/# apt -get intsall vim #安装vim
[root@localhost ~] docker commit -m="vim cmd add ok" -a="lfz" bf9b18b76e62 ubuntu/vim:1.1#提交容器副本让其成为一个新的镜像,这样就得到一个带vim的Ubuntu镜像了
镜像创建过程:
5.2将镜像发布到阿里云
登录阿里云,控制台-容器镜像服务-选择个人实例-创建命令空间-创建镜像仓库
创建完阿里云会自动生成代码
将镜像push推送到阿里云镜像仓库:
阿里云上面创建完仓库会有如何推送镜像教程
$ docker login --username=xxx registry.cn-hangzhou.aliyuncs.com #自己的useename账号
$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/lfz_docker/ubuntu1.1:[镜像版本号]
$ docker push registry.cn-hangzhou.aliyuncs.com/lfz_docker/ubuntu1.1:[镜像版本号]
从阿里云push下载镜像验证:
docker login --username=xxx registry.cn-hangzhou.aliyuncs.com
docker pull registry.cn-hangzhou.aliyuncs.com/lfz_docker/ubuntu1.1:[镜像版本号]
5.3将本地镜像发布到DockerHub
在dockerhub注册并创建仓库ubuntu
登录dockerhub
docker login
输入用户名和密码
修改镜像名符合规范并推送
docker tag ubuntu:1.1 liufengzhi/ubuntu:1.1
docker push liufengzhi/ubuntu:1.1
注意只有官方仓库的镜像不带全路径,非官方镜像都会带全路径,所以说推送镜像必须改镜像的名字,让其符合规范