Docker——Docker 镜像详解

Docker镜像是什么

  • Docker 容器的运行是基于宿主机的内核,通过linux的namespaces来实现隔离,相对于虚拟机而言降低了硬件资源的性能损耗,且具备一定程度上的应用隔离效果。
  • 镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
  • 通过最小化的镜像方式运行docker 容器,相对于虚拟机而言大幅度降低非生产力进程的资源消耗。
  • 所有应用,直接打包成docker镜像,就可以在其他服务器上直接运行起来!
  • Docker 客户端启动一个容器时,通过TCP或者unix socket连接docker daemon。如果需要启动的容器镜像本地不存在,则从registry来拉取到本地,然后根据传递的CMD或者默认的CMD来启动容器。
    在这里插入图片描述

Docker镜像加载原理

联合文件系统(UnionFS)

  • UnionFS( 联合文件系统) : Union文件系统(UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。
  • Union文件系统是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等等。
    在这里插入图片描述
  1. 一开始内核里什么都没有,操作一个命令下载debian
  2. 安装一个emacs,就在内核上面加了一层images
  3. 安装一个apache,又在上面再加一层
  4. 下面每一层都是公用的

Docker里的centos的大小才200m

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

镜像分成理解

Docker镜像采用分层结构的好处:

  • 资源共享,比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务,而且镜像的每一层都可以被共享
使用docker image inspect 镜像名 查看镜像分层
docker image inspect tomcat

"RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:e2c6ff46235709f5178ab7c1939f4fba7237ffde84e13b1582fa5f0837c1d978",
                "sha256:26270c5e25fa4569f37428604f708f8863a171ec2499a066241a641017971308",
                "sha256:a42439ce96509df457152574716e3c07a8d5640fe9c16f5d4fb8854f72ce357a",
                "sha256:5d5962699bd5f016d81fc6d623cb0bc1f3853efdc48b6958053122caffc425de",
                "sha256:26863b4714ee050f833364c81528e499eeff4f778cde2064e2db4cb24b289f08",
                "sha256:e8ef11c449dc031843c8689705b8348da5931ae611b46bfaceaa974b7832fe43",
                "sha256:825d742348a7bd1509510b17a2ffcdedfbd601f2f06e27441c048edd24d76e40",
                "sha256:7d8560b35c34638f13784a532581d1741f21a4f8f313f6715f127f7a22612983",
                "sha256:447f25b09d03785e0c1a5bd581d2f2880fe315e2e5f3e78f02f7d2fb224a1ad4",
                "sha256:bc7727a11f1ace90fd41701385cdd08659866de174873a3e3b550dcab1d717db"
            ]
        },

这个Layers就是分层
  • 所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

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

  • 该镜像当前已经包含3个镜像层
    在这里插入图片描述

  • 在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
    在这里插入图片描述

  • 上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

  • 下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
    在这里插入图片描述

  • 这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

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

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

  • 下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
    在这里插入图片描述

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

  • 这一层就是通常说的容器层,容器之下的都叫镜像层

Commit镜像

提交一个自己制作的镜像

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

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

先创建一个tomcat容器
docker run -it -p 9000:8080 --name tomcat01 tomcat /bin/bash

进入容器修改
cp -r webapps.dist/* webapps/

将修改后的容器提交成一个新的镜像
docker commit -a="maomao" -m="add webapps" dd3e1a74ea4f tomcat02:1.0

docker images

REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
tomcat02              1.0       17282ff7d785   5 seconds ago   672MB

测试
[root@docker run]# docker run -it -p 9000:8080 --name ceshi 172 /bin/bash
root@ec8413e7f4f7:/usr/local/tomcat# ls
BUILDING.txt	 LICENSE  README.md	 RUNNING.txt  conf  logs	    temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin	      lib   native-jni-lib  webapps  work
root@ec8413e7f4f7:/usr/local/tomcat# cd bin/
root@ec8413e7f4f7:/usr/local/tomcat/bin# ./startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/local/openjdk-11
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
Tomcat started.

不需要像之前一样修改webapps目录 就能够访问网页了

在这里插入图片描述

镜像的总结

在这里插入图片描述

  • 基于运行中的容器,手动制作镜像
    • 将运行中的容器暂停(docker commit 默认暂停容器),然后将当前的状态制作成镜像,注意需要指定repository,只要 -a添加作者信息,-c修改其它字段信息,常修改CMD信息。
    • 导出(export)当前容器的文件系统信息,导出后的格式为.tar,.tar文件是一个中间状态的文件,需要使用import导入并且设置CMD等相关信息才是一个完整的镜像。
  • 自动化制作镜像 Dockerfile
    Dockerfile 能解决两个问题:
    • 制作过程自动化:原理也是先运行容器,然后再基于运行的容器制作镜像,但是将制作过程使用dockerfile预先指定好
    • 可以引入变量:在制作镜像时手动传参,根据传递的参数制作不同的镜像;在创建容器时手动传参,根据传递的参数修改进程的配置
  • 镜像导出和导入
    • 这并不是制作镜像,而是共享或传输镜像到其它服务器的一种方式,如果局域网中存在registory,这种方式意义不大。
    • 如果局域网中没有registory,通过公网下载镜像会变得非常慢,因此将需要的镜像在一台机器上打包好,分发到各台服务器上会更加节约时间。
  • 10
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值