赞
踩
本篇主要是介绍一下docker的镜像和容器数据卷的理论
首先我们抱着一个疑问,镜像是什么?
在实际开发中,可能遇到相同的复制环境就是镜像,在docker中,镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的所有内容,包括代码、运行时、库、环境变量和配置文件。
UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union文件系统是Dokcer镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统加载起来,这样最终的文件系统会包含所有的底层文件和目录。
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等等。
我们看看docker中的centos,才200多M
对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直 接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一 致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
可以看到我们在下载镜像的时候,分了很多层
查看镜像的分层方式可以通过docker image inspect命令
所有的 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镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
docker commit 从容器创建一个新的镜像。
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[标签名tag]
前几篇我们docker里启动的tomcat没有首页,是因为他的webapps下确实没有任何文件,今天我们再来具体看看
首先docker启动一个tomcat
[root@feng ~]# docker run -it -p 8090:8080 tomcat
这里我挂在8090端口的
#查看一下tomcat的容器id [root@feng ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2a86a1dffb5f tomcat "catalina.sh run" 33 seconds ago Up 31 seconds 0.0.0.0:8090->8080/tcp determined_ramanujan 455bdc084fe9 portainer/portainer "/portainer" 15 hours ago Up 14 hours 0.0.0.0:8088->9000/tcp prtainer #进入这个tomcat的bash页面 [root@feng ~]# docker exec -it 2a86a1dffb5f /bin/bash #看看webapps有什么 root@2a86a1dffb5f:/usr/local/tomcat# cd webapps root@2a86a1dffb5f:/usr/local/tomcat/webapps# ls #果然啥也没有 root@2a86a1dffb5f:/usr/local/tomcat/webapps# cd .. #我们发现有一个webapps.dist的文件夹,里面有东西 root@2a86a1dffb5f:/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 #把他复制到webapps下看看 root@2a86a1dffb5f:/usr/local/tomcat# cp -r webapps.dist/* webapps root@2a86a1dffb5f:/usr/local/tomcat# cd webapps root@2a86a1dffb5f:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager root@2a86a1dffb5f:/usr/local/tomcat/webapps#
此时运行的tomcat实例就是一个没有docs的容器,我们使用它为模板commit一个没有docs的tomcat新镜像,tomcat02
[root@feng ~]# docker commit -a="feng_tomcat" -m="no tomcat docs" 2a86a1dffb5f tomcat02:1.1
sha256:cf161fd1393d177c5e07ffac8c6a98c463965f2866a9ce65c0aac3bd960c39a8
[root@feng ~]#
再docker images一下,发现自己提交的docker镜像已经有了
我们也可以启动看看
[root@feng ~]# docker run -it -p 8090:8080 tomcat02:1.1
可以看到没有问题,随便启动
随便进
docker的理念回顾:
将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够 持久化的!
就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了,显然不合理吧。
所以我们希望容器之间有可能可以共享数据,Docker容器产生的数据,如果不通过docker commit 生成 新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行 不通的!
为了能保存数据在Docker中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除 而丢失了!
作用:
卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此 能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性:
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂 载的数据卷。
特点:
1、数据卷可在容器之间共享或重用数据
2、卷中的更改可以直接生效
3、数据卷中的更改不会包含在镜像的更新中
4、数据卷的生命周期一直持续到没有容器使用它为止
其实我们命令篇已经涉及到了一些简单的挂载命令,这里细讲
# 命令
docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名
# 测试
[root@feng ~]# docker run -it -v /home/ceshi:/home centos /bin/bash
怎么看是否挂载成功?
使用查看容器详情命令
docker inspect 容器id
测试挂载
可以发现在宿主机和容器中互相修改对应文件,数据同步
除了具名挂载,甚至还有匿名挂载
所有docker的卷没有指定目录的情况下都在cd /var/lib/docker/volumes/**/_data 下,通过具名挂载可方便地找到我们的卷,大多数情况下使用的都是具名挂载
如何确定是具名挂载、匿名挂载还是指定地址挂载
-v 容器路径 #匿名挂载
-v 卷名:容器类路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
# 改变文件的读写权限
# ro: readonly
# rw: readwrite
# 指定容器对我们挂载出来的内容的读写权限
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx
#ro表示这个路径只能通过宿主机操作,容器无权限操作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。