Docker 存储驱动详细介绍_java

Docker 存储驱动详细介绍

最近做项目,期间对Docker 存储驱动不会,于是在网上找资料,并解决了,这里就记录下。

目的

  1. 理解docker的存储方式
  2. docker的image和container在host上的目录结构
  3. docker image和container的内容与配置不同存储

Docker是一个开源的应用容器引擎,主要利用Linux内核namespace实现沙盒隔离,用Cgroup实现资源限制。Docker用于统一开发和部署的轻量级 Linux 容器,试图解决“依赖地狱”问题,把依赖的服务和组件组合起来,类似船舶使用的集装箱,达到快速安装部署。

1. Docker的基本架构—Client和Daemon

让我们先搞明白docker的基本架构和启动过程,其实Docker 采用了C/S架构,包括客户端和服务端。Docker daemon作为服务端接受来自客户的请求,并处理这些请求(创建、运行、提交容器)。 客户端和服务端在一个机器上,通过RESTful API 来进行通信。 具体到使用的过程中,就是在执行 service docker start 后,在主机(host)上产生docker deamon守护进程,在后台运行并等待接收来自客户端的消息(即输入的docker命令,如 docker pull xxx,docker run …,docker commit xxx ),实现跟docker deamon的交互。当启动docker服务后,可以看到docker进程。

Default

[root@localhost ~]# ps -aux | grep docker
root  11701 0.0 0.4 359208 16624 ?  Ssl 21:05 0:00 /usr/bin/docker -d -H fd:// --selinux-enabled --insecure-registry 186.100.8.216:5000
root  11861 0.0 0.0 113004 2256 pts/0 S+ 23:01 0:00 grep --color=auto docker

说明这个,主要是后面指定文件系统的时候,需要先在 /etc/sysconfig/docker 的配置具体的storage driver(这个会写一篇专门的Blog),然后再启动Docker Daemon,而不能通过run命令的参数进行操作。还可以直接在host命令行通过 docker –d 进行设置。

2. Docker的存储方式—Storage Driver

Docker模型的核心部分是有效利用分层镜像机制,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。其中主要的机制就是分层模型和将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem,来自 这篇文章 )。 针对镜像存储docker采用了几种不同的存储drivers,包括:aufs,devicemapper,btrfs 和overlay(来自 官网 )。下面简单对不同的存储drivers做个介绍。

AUFS

AUFS(AnotherUnionFS)是一种联合文件系统。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。AUFS唯一一个storage driver可以实现容器间共享可执行及可共享的运行库, 所以当你跑成千上百个拥有相同程序代码或者运行库时时候,AUFS是个相当不错的选择。

Device mapper

Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略( 详见 ) 。Device mapper driver 会创建一个100G的简单文件包含你的镜像和容器,每一个容器被限制在10G大小的卷内(注意:这是利用loopback自动创建的稀疏文件,具体为 /var/lib/docker/devicemapper/devicemapper 下的data和metadata,可动态扩张)。可以调整Docker容器的大小, 具体参考 ) 你可以在启动docker daemon时用参数-s 指定driver,也就是可以 docker -d -s devicemapper 设置docker的存储driver。先关闭docker服务,执行命令:

Default

[root@localhost ~]# docker -d -s devicemapper
INFO[0000] +job serveapi(unix:///var/run/docker.sock)
INFO[0000] Listening for HTTP on unix (/var/run/docker.sock)
INFO[0000] +job init_networkdriver()
INFO[0000] -job init_networkdriver() = OK (0)
INFO[0000] Loading containers: start.
....
INFO[0000] Loading containers: done.
INFO[0000] docker daemon: 1.4.0 4595d4f/1.4.0; execdriver: native-0.2; graphdriver: devicemapper
INFO[0000] +job acceptconnections()
INFO[0000] -job acceptconnections() = OK (0)

另外,docker在启动容器的时候可以指定 –storage-opt 参数,但是现在只有devicemapper能够接受参数设置。后面会有针对性的Blog展示。

BTRFS

Btrfs Driver 在docker build可以很高效。但是跟 devicemapper 一样不支持设备间共享存储(参加 官网 )。Btrfs 支持创建快照(snapshot)和克隆(clone),还能够方便的管理多个物理设备。(详细了解可以参考 IBM对Btrfs的介绍 )

overlay

overlay跟AUFS很像,但是性能比AUFS好,有很好内存利用,现在已经合并入Linux内核3.18了。具体使用命令: docker –d –s overlay

官网的Note: It is currently unsupported on btrfs or any Copy on Write filesystem and should only be used over ext4 partitions.

3 Docker目录结构

Docker两个最重要的概念是镜像和容器。那么我们pull下来的镜像的存储在哪里呢?镜像运行容器启动后,我们的操作修改的内容存储在哪里呢?因为具体的驱动不同,所以最终的实现效果不同。下面我们以Device Mapper存储driver为例,分析下docker的存储结构。

1. 进入 /var/lib/docker 目录,列出内容:

Default

[root@localhost ~]# cd /var/lib/docker/
[root@localhost docker]# ls
containers devicemapper execdriver graph init linkgraph.db repositories-devicemapper tmp trust volumes

根据目录的内容,可以明显的看到是使用了devicemapper driver。

注:以下显示的文件夹都是在/var/lib/docker下的。

2. pull的镜像文件存在哪个文件夹下呢?( 参考 )

pull的镜像信息保存在了graph文件夹下,镜像的内容存在了 devicemapper/ devicemapper/data 下。

3. 启动的容器运行在哪里呢?

启动的容器配置信息保存在 containers 里,查看了还有 execdriver/native/ 。

容器里操作的内容保存在 devicemapper/devicemapper/data 下。

4. graph的角色

在Docker架构中扮演已下载容器镜像的保管者,以及已下载容器镜像之间关系的记录者。graph的本地目录中,关于每一个的容器镜像,具体存储的信息有:该容器镜像的元数据(json),容器镜像的大小(layersize)信息,以及该容器镜像所代表的具体rootfs。

5. 实验测试:

- 初始没有启容器:

Default

[root@localhost docker]# ll containers/
total 0

- 启动一个容器:

Default

[root@localhost docker]# docker run -i -t --rm centos:7 /bin/bash
[root@187a8f9d2865 /]#

所启动的容器的 UUID=187a8f9d2865

- 启动容器前,查看查看/var/lib/docker/devicemapper/devicemapper/下文件的实际大小

Default

[root@bhDocker216 docker]# du -h devicemapper/devicemapper/*
2.1G devicemapper/devicemapper/data
3.5M devicemapper/devicemapper/metadata

- 在host的主机上查看

Default

[root@bhDocker216 docker]# ls containers/
187a8f9d2865c2ac***91b981

查看启动的容器在UUID文件夹下面的内容:

Default

[root@bhDocker216 containers]# ll 187a8f9d2865c2ac***91b981
total 24
-rw-------. 1 root root 273 Mar 5 23:59 187a8f9d2865***-json.log
-rw-r--r--. 1 root root 1683 Mar 5 23:58 config.json
-rw-r--r--. 1 root root 334 Mar 5 23:58 hostconfig.json
-rw-r--r--. 1 root root 13 Mar 5 23:58 hostname
-rw-r--r--. 1 root root 174 Mar 5 23:58 hosts
-rw-r--r--. 1 root root 69 Mar 5 23:58 resolv.conf
- 在启动的容器添加文件,并查看。

先在运行的容器内创建一个文件:

Default

[root@8a1e3ad05d9e /]# dd if=/dev/zero of=floppy.img bs=512 count=5760
5760+0 records in
5760+0 records out
2949120 bytes (2.9 MB) copied, 0.0126794 s, 233 MB/s

然后在/var/lib/docker/devicemapper/devicemapper/下查看文件:

Default

[root@bhDocker216 docker]# du -h devicemapper/devicemapper/*
5.5G devicemapper/devicemapper/data
4.6M devicemapper/devicemapper/metadata

这地方大小有点出入,是因为先执行了 # dd if=/dev/zero of=test.txt bs=1M count=8000 ,创建一个8G大小的文件,由于太慢我终止了,但是可以明确的看到在运行的容器里进行操作,两个文件夹都发生了改变(增加)。

- 查看graph,在只pull了一个镜像(Ubuntu14.10)的情况下,里面出现了7个长UUID命名的目录,这是怎么来的呢?

用 docker images –tree 列出镜像树形结构,我们可以看到镜像的分层存储结构。最终的Ubuntu(第7层)是基于第6层改动的,即这种逻辑上的树中第n层基于是第n-1层改动的,n层依赖n-1层的image。第0层,大小为0,称为base image。

- graph/UUID目录下内容是啥呢?

Default

[root@localhost graph]# ll 01bf15a18638145eb*** -h
total 8.0K
-rw-------. 1 root root 1.6K Mar 5 18:02 json
-rw-------. 1 root root 9 Mar 5 18:02 layersize

查看layersize的内容:数字表示层的大小(单位:B)。 josn:保存了这个镜像的元数据(如: size,architecture,config,container,**parent的UUID** 等等)。

- 查看devicemapper/devicemapper文件夹

有两个文件夹 data 和 metadata ,其实device mapper driver是就是把 镜像和容器的文件 都存储在 **data** 这个文件内。可以通过docker info查看data和metadata的大小。 另外可以用 du –h (上面有用到)查看这两个稀疏文件的实际大小。

- execdriver

Default

[root@bhDocker216 docker]# ls execdriver/native/
8a1e3ad05d9e66a455e683a2c***2437bdcccdfdfa
//对里面的内容进行查看:
[root@bhDocker216 8a1e3ad05d9e66a455e***]# ls
container.json state.json

- volumes

没有加-v参数的volumes是空的,经测试如果启动容器增加加-v参数,volumes文件夹下将显示一个UUID,在host进行全局搜索,只在volumes下找到了,跟镜像和容器的UUID都没有关系。

Default

[root@bhDocker216 docker]# find / -name 86eb77f9f5e25676f100***d5a
/var/lib/docker/volumes/86eb77f9f5e25676f100***d5a
//查看里面的内容:
[root@bhDocker216 volumes]# ls 86eb77f9f5e25676f100***d5a
config.json
[root@bhDocker216 volumes]# cat 86eb77f9f5e25676f100***d5a /config.json
{"ID":"86eb77f9f5e25676f100a89ba727bc15185303236aae0dcf4c17223e37651d5a","Path":"/home/data","IsBindMount":true,"Writable":true}

文件夹作用表格性说明

做个总结,整理一个表格,把/var/lib/docker下的不同文件夹作用说明下:

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索docker
, 存储驱动
, 存储驱动详解
存储驱动介绍
docker 存储驱动、docker存储驱动设置、docker 显卡驱动、docker 超详细、非常详细的docker,以便于您获取更多的相关知识。

时间: 2024-09-11 01:37:17

Docker 存储驱动详细介绍_java的相关文章

深入了解Docker存储驱动

本文讲的是深入了解Docker存储驱动[编者的话]本文深入探讨了Docker容器的存储驱动,内容包括graphdriver以及各个选项比如Vfs.Aufs.Overlay.Overlay2.Btrfs.ZFS.Devicemapper和Windows,还有具体如何选择的规则. 如果你曾经上手用过Docker,你可能已经见过存储驱动(storage driver)这个词.或者你已经偶然听过graphdriver这个词,并心想这到底是个什么鬼?或者你听过大牛们谈论的话题中出现的aufs和device

对Docker存储驱动的评价

本文讲的是对Docker存储驱动的评价,[编者的话]Docker 的生态系统不断完善,上到容器的编排发布,下到网络存储,都有着各种选择.对于Docker 最底层的存储驱动,也有着Overlay.Zfs等选择,各有利弊,本文从一位使用者的角度对不同的驱动发表了自己的看法,仅供参考. 温馨提示,本文的所有观念谨代表个人看法,所以不要因为你不同意我,就在Hacker News 上和我争论.我可以不那么公正,因为这是我自己的看法. 很坦率的说,我认为每种Docker存储驱动都不好用,所以你要决定哪一种最

Java类加载基本过程详细介绍_java

Java类加载基本过程详细介绍 基本过程: 根据类的全限定名称加载定义类的二进制字节流. 将字节流代表的静态存储结构转化为方法区的运行时数据结构 内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类的各种数据访问入口  数组类本身不通过类加载器创建,由java虚拟机直接创建,数组类的元素类型由类加载器加载. 数组类的元素类型:数组去掉所有维度后的类型,  文件格式验证: 0xCAFEBABY 魔数开头: 主次版本号当前虚拟机可处理: 常量类型: 索引执行类型: utf8

JAVA和JAVAC 命令详细介绍_java

JAVA和JAVAC 命令 javac和java命令行中的-classpath选项 这是个很基础的问题,但是因为基本上都是用现有的IDE工具 来开发java程序,所以很少有人意识到这一点. javac -classpath,设定要搜索类的路径,可以是目录,jar文件,zip文件(里面都是class文件),会覆盖掉所有在CLASSPATH里面的设定. -sourcepath, 设定要搜索编译所需java 文件的路径,可以是目录,jar文件,zip文件(里面都是java文件). 所以一个完整的jav

Java 高并发五:JDK并发包1详细介绍_java

在[高并发Java 二] 多线程基础中,我们已经初步提到了基本的线程同步操作.这次要提到的是在并发包中的同步控制工具. 1. 各种同步控制工具的使用 1.1 ReentrantLock ReentrantLock感觉上是synchronized的增强版,synchronized的特点是使用简单,一切交给JVM去处理,但是功能上是比较薄弱的.在JDK1.5之前,ReentrantLock的性能要好于synchronized,由于对JVM进行了优化,现在的JDK版本中,两者性能是不相上下的.如果是简

IISExpress 配置允许外部访问详细介绍_java

 IISExpress 配置允许外部访问详细介绍 1.找到IISExpress的配置文件,位于 <文档>/IISExpress/config文件夹下,打开applicationhost.config,找到如下代码: <site name="WebSite1" id="1" serverAutoStart="true"> <application path="/"> <virtualDi

JAVA JNI函数的注册过程详细介绍_java

JAVA JNI函数的注册过程详细介绍 我们在java中调用Native code的时候,一般是通过JNI来实现的,我们只需要在java类中加载本地.so库文件,并声明native方法,然后在需要调用的地方调用即可,至于java中native方法的具体实现,全部交给了Native层.我们要在java中正确地调用到本地代码中对应函数的前提是什么呢?答案就是通过一定的机制建立java中native方法和本地代码中函数的一一对应关系,那么这种机制是什么呢?就是JNI函数的注册机制. JNI函数的注册有

Web Service 运行原理详细介绍_java

     利用清明小假期,温习了一遍Web Service的相关内容,对其工作原理进行了简要总结.以供有需求的朋友和自己日后参考.文章若有不当之处,敬请朋友们提出宝贵建议,以求共勉.       Web服务中,我们应该首先了解相关的术语含义:WSDL.UDDI....相关术语方面的介绍在此不再赘述,重点放在原理上. 在Web服务中,存在三个角色:服务提供者.服务请求者和服务中介,三者之间的关系如图1-1所示     实现一个完整的Web服务包括以下步骤:    ◆ Web服务提供者设计实现Web

java String类常量池分析及&quot;equals&quot;和&quot;==”区别详细介绍_java

java "equals"和"=="异同 首先简单说一下"equal"和"==" ==操作对于基本数据类型比较的是两个变量的值是否相等, 对于引用型变量表示的是两个变量在堆中存储的地址是否相同, 即栈中的内容是否相同 equals操作表示的两个变量是否是对同一个对象的引用, 即堆中的内容是否相同. 综上,==比较的是2个对象的地址,而equals比较的是2个对象的内容. 再简单介绍一下String类 String类 又称作不可