linux docker 存储位置,docker image是什么,存储在什么位置

本文回答两个问题:

1.docker image是什么。

2.docker image存储在哪里,以什么形式存储。

1.dockerimage是什么

image里面是一层层文件系统,叫做Union FS(联合文件系统)。联合文件系统,可以将几层目录挂载到一起,形成一个虚拟文件系统。虚拟文件系统的目录结构就像普通linux的目录结构一样,docker通过这些文件再加上宿主机的内核提供了一个linux的虚拟环境。每一层文件系统我们叫做一层layer,联合文件系统可以对每一层文件系统设置三种权限,只读(readonly)、读写(readwrite)和写出(whiteout-able),但是docker镜像中每一层文件系统都是只读的。

构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统。一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样。当你使用的时候,你只会看到一个完全的整体,你不知道里面有几层,也不清楚每一层所做的修改是什么。结构类似这样:

1aa3c81f0260cbe5dad22a6ceeffc166.png

从基本的看起,一个典型的Linux文件系统由bootfs和rootfs两部分组成,bootfs(boot file system)主要包含bootloader和kernel,bootloader主要用于引导加载kernel,当kernel被加载到内存中后bootfs会被umount掉。rootfs (root file system)包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。下图就是docker image中最基础的两层结构,不同的linux发行版(如ubuntu和CentOS )在rootfs这一层会有所区别,体现发行版本的差异性。

3523e1c4550af3fa94fccb6de948f1bd.png

传统的Linux加载bootfs时会先将rootfs设为read-only,然后在系统自检之后将rootfs从read-only改为read-write,然后我们就可以在rootfs上进行读写操作了。但Docker在bootfs自检完毕之后并不会把rootfs的read-only改为read-write,而是利用union mount(UnionFS的一种挂载机制)将image中的其他的layer加载到之前的read-only的rootfs层之上,每一层layer都是rootfs的结构,并且是read-only的。所以,我们是无法修改一个已有镜像里面的layer的!只有当我们创建一个容器,也就是将Docker镜像进行实例化,系统会分配一层空的read-write的rootfs,用于保存我们做的修改。一层layer所保存的修改是增量式的,就像git一样。

46ab21fce5b85049a2e239ff18187b16.png

综上,image其实就是一个文件系统,它与宿主机的内核一起为程序提供一个虚拟的linux环境。在启动docker container时,依据image,docker会为container构建出一个虚拟的linux环境。

2.dockerimage存储在哪里,以什么形式存储。

当运行sudo docker pull ubuntu命令,从Docker HUB上下载一个ubuntu image后,这个image存储在宿主机的什么位置,以什么形式存储的呢。下面我们一步步来揭开这个答案。

Docker目前支持五种镜像层次的存储driver:aufs、device mapper、btrfs、vfs、overlay。下面以aufs做介绍,这个也是我们系统上用的。

下载一个ubuntuimage,修改tag为xuzw,删除其他所有镜像。

add533d3f2b00dc5b6447772b27275b2.png

在安装docker时,默认的安装位置是/var/lib/docker。让我们看看这个目录下面都有什么。

89ca5cdd440d88453827018908f6b100.png

repositories-aufs:记录了镜像名称以及对应的Id的json文件,

1f846481883734c6941fa5b1d8f6a71c.png

graph:保存的是下载镜像的元数据,包括json和layersize,其中json文件记录了相应的image id、依赖关系、创建时间和配置信息等。layersize为对应层的大小。进入graph文件会发现下面包含着多个文件夹,其中有一个是以我们下载的镜像命名的文件夹ca4……,进入这个文件夹,可以看到json和layersize文件。

22f51ba2230e5986ddb710288d7cffe1.png

json文件内容部分截图如下,layersize显示为0。怎么会为0呢,不用着急,这一层为0,不表示镜像大小就是0。Graph存储镜像时,是分层存储的,graph目录下多出的文件夹其实都对应一个layer。这些layer都与我们的镜像名命名的layer有关联,关系就记录在json文件中。

992c458cc9f2028e30578ab946d88541.png

从这个json文件中,可以看到起父镜像或者上一层镜像就是a46……,graph目录下也存储着这一层的信息。再往下看,可以看到层次关系是:ca4--> a46--> ea3--> 233。

在graph这个目录里并没有找到我们想找到的镜像内容存放地。graph目录下只是一些镜像相关的信息数据。由上一节我们已经知道,image应该包含一个类似linux的文件系统才对。

containers:这个下面记录的是容器相关的信息,每运行一个容器,就在这个目录下面生成一个容器Id对应的子目录,如下图。

c325cf60aaff51deedfebbea56cf325e.png

init:保存的是docker init相关的信息。

tmp:是一个空目录,具体起什么作用还不清楚。

volumes:与docker的数据券相关,在此不进行扩展。

现在就只剩下aufs这个目录没有看了,进入aufs这个目录。

c638dbcd67acf27da8233d4ad8ccd619.png

mnt是aufs的挂载目录,diff是实际数据来源,也就是我们image实际存储的地方,包括只读层和可读写层,所有这些层最终都一起挂载到mmt所在的目录。layers下为每层依赖有关的描述文件。

在diff、mnt、layers下面有6个文件或子目录,但是从graph目录下看我们的image应该是4层,为什么会多出来2个呢。仔细观察多出来的来个文件或者子目录,会发现其名称和容器Id一致,且有一个包含init。这是为什么呢?

其实,在容器启动之前,mnt和layers都是空目录,diff下面也只有graph目录下我们看到的镜像层对应的4个目录。

在Docker利用image启动一个容器时,会在aufs下新建容器id对应的文件和子目录,同时在镜像的可读层执行新建一个可读写的layer。至于id-init文件或者子目录记录的都是与容器内环境相关的信息,与镜像无关。

既然我们现在已经知道了镜像实际是存储在diff目录下的,那么我们就看看diff目录下各个子目录中的内容。依照镜像的层次关系ca4--> a46--> ea3- -> 233查看。

78588a8acdf19f415032132cf6e2f5d7.png

最终我们看到linux一样的文件系统。已表示image确实是存储在diff目录下的。综上,dockerimage最终是存储在在/var/lib/docker/aufs/diff中的,同时在graph中有有关进行的记录。在容器启动时,diff下的可读层image和新增的可读写层“容器Id”都将挂载到mmt目录下以容器id命名的子目录下。

参考资料:http://blog.csdn.net/jcjc918/article/details/46500031

转载地址:http://www.aboutyun.com/home.php?mod=space&uid=31226&do=blog&id=2850&&mobile=no

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值