■  磁盘空间和docker资源之间的关系(devicemapper驱动)

  通过docker info | grep Space可以看到Docker占据的磁盘空间的信息。其中Data Space Used表示实际上docker资源占用掉的磁盘空间。相对应的Metadata Space Used是表示了所谓的metadata占据空间的大小。

  data和metadata默认情况下是放在/var/lib/docker/devicemapper/devicemapper中。由于一般/var属于系统盘,而系统盘的大小是比较小的,所以docker很容易占满整个系统盘的空间。所以最好在启动docker的时候指定一个数据盘上的另一个目录作为docker运行时的根目录。通过dockerd的-g或者--graph参数指定。

  另一方面,我们还可以在docker应用的这个层面限制一下docker资源最多可占用的空间的大小。这个数据体现在docker info中的Data Space Total,这个数字是docker启动时配置项可配置的,不是真的磁盘中的总空间。也就是说这个数字有可能是大于docker运行时目录所在磁盘的总空间的,它从docker应用层限制了docker发展的大小。

  这个数字的设置方法是dockerd --storage-opt dm.loopdatasize=500G --storage-opt dm.loopmetadatasize=20G --storage-opt dm.basesize=8G,三个参数限制的分别是docker资源总大小,metadata总大小,单个镜像的最大大小。在启动时配合docker运行时根目录所在磁盘的实际空间,设置一个合适的大小,可以避免docker把磁盘挤满这种事情的发生。

  如果使用systemctl的方式来启动docker的话可以修改/lib/systemd/system/docker.service文件,这个文件是通过systemctl启动dockerd时的各个参数,修改其中的ExecStart加上前面说的几个参数即可。

  ●  扩容

  如果在docker运行过程中发现了大小不够要扩容了,遵循上面的原理,大概可以这么操作。1. 备份所有镜像和容器,因为到时候会删掉原有data文件并创建新的。2.关停docker服务,像上面说的那样进行启动参数的更改。 3. 删除原有的数据文件,并利用dd命令生成一个指定大小的数据文件,参考【http://blog.csdn.net/TinyJian/article/details/78436739】:

sudo rm -rf /var/lib/docker
sudo mkdir -p /var/lib/docker/devicemapper/devicemapper/
sudo dd if=/dev/zero of=/var/lib/docker/devicemapper/devicemapper/data bs=1M count= seek=
sudo dd if=/dev/zero of=/var/lib/docker/devicemapper/devicemapper/metadata bs=1M count= seek=

  然后重启docker服务即可:

sudo systemctl daemon-reload
sudo systemctl start docker

  对于空间不够等情况,除了要扩容,更重要的应该是及时清理不要用的容器和镜像。对于镜像,在Linux上可以简单的认为是一个文件,删掉就会减少占用空间,新增就会增加占用空间。在其他一些系统如OSX上则可能会出现删掉了镜像但是空间没有空出来这种事。 * 其实在Linux上也不尽然,生成的镜像即使立刻删除,从dockerinfo的结果来看,似乎也总是会留一点东西在系统中。随着镜像的不断增多,系统的空间肯定是会一点一点变小的。

  对于容器,当一个容器被生成,容器中的内容自然是作为docker数据的一部分被写入磁盘的。容器在生命周期中,在磁盘中空间占用情况是只增不减的。也就是说当我在容器中建了一个1G的文件,磁盘自然多了1G占用,如果再建一个0.5G的文件,磁盘占用就到了1.5G。此时再把第二个文件删掉,虽然容器中看起来占据空间减少了,但是外面的磁盘中依然维持1.5G占用。除非把这个容器删除。

  

■  关于利用python的subprocess模块与docker exec进行互动

  今天遇到个很操蛋的需求,要批量修改容器中的root用户密码。本以为不是什么难事,结果没想到那台主机不能接外网且没有paramiko,docker-py等其他模块。想来想去恐怕只能使用subprocess这个内建的模块来做一做。

  因为是subprocess,所以无疑是在主机本地做操作,而从本地最方便的办法就是通过类似于docker exec -ti <container> /bin/bash来进入到容器里面操作。手动尝试了下,更加操蛋的是容器都用了一个镜像且这个镜像里居然没有passwd命令。。视图装Passwd搞了半天都失败,只好用chpasswd来做。但是chpasswd直接docker exec -ti <container> 后面跟chpasswd的一些操作时总是无法顺利将容器内密码修改(相反还改了宿主机密码好几次)。最终还是绕回到用subprocess上来。

  一开始用subprocess的经典方法,运行这条命令时总是报错stdin is not tty之类的错误,后来注意到要去掉-t参数。所以通过subprocess修改一个容器的用户的密码的代码如下,如果将chpasswd命令部分换成其他命令也可以看成是通过subprocess,在宿主机本地来和容器做交互的一种途径:

from subprocess import *

p = Popen('docker exec -i test /bin/bash',shell=True,stdin=PIPE,stdout=PIPE,stderr=PIPE)
# 去掉了-t参数,test为容器名,stdin为PIPE是为了communicate时能够向身为子进程的容器伪终端传递更多命令 out,err = p.communicate(input='echo root:123456|chpasswd\nexit\n')
# 此时密码已经改变,原先为终端中的两行命令通过换行符放在一行中

■  关于容器内外时间同步性问题

  容器内时间和容器外时间(即宿主机的时间)可能会发生不同步的情况。如果刚好差了八个小时,可能是因为两者没用采取统一的时区制。比较常见的情况是容器时间比宿主时间晚八个小时。即容器中采用的是UTC而宿主机使用了CTS-8时区。

  此时解决的办法是修改Dockerfile或者在容器启动时加入参数,把宿主机的/etc/localtime挂载到容器的/etc/localtime,此时容器就可以保持和宿主的时间一致了。

  

  另一种反过来的问题是,docker是对文件系统的虚拟,容器和宿主机使用的仍然是一套相同的linux内核。然而时间日期调取是内核方法,使得比如当使用date -s修改宿主机or容器的时间时,另一边也会被修改。如何才能做到容器和宿主机时间不同步?

  在网上找到了一个比较好的解决方案:https://github.com/wolfcw/libfaketime/,将这个libfaketime项目下载下来,然后用make,make install的方式安装到容器中(注意容器中要有gcc以及make相关组件,如果没有建议yum安装下),然后在容器中设置一个环境变量:

export LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.

  之后在这个shell环境中使用date命令,或者其他的一些什么程序调用内核获取时间日期的方法就可以修改了。修改的方式是在获取之前设置一个名为FAKETIME的环境变量,如export FAKETIME="+8h"。这就是表示容器中的时间保持原时间基础上加上8个小时的时间。export过后在容器内外分别运行date命令就可以看到两者的不同了。+8h这块的语法可以参见项目主页的文档。

  * 在用了这个方案之后,容器将默认用回UTC时间。可能是因为libfaketime这个库绕开了内核获取时间的同时也绕开了读取/etc/localtime。这个不知道该怎么解决比较好,但是在faketime的基础上可以先export FAKETIME="+8h",先使得容器内外时间同步且为北京时间。知晓这个的基础上,我们在设置不同的FAKETIME来设置不同的容器内时间。

  值得一提的是,FAKETIME可以设置成一个固定的时间,格式是%Y-%m-%d %X,但是这是固定的,如果设置那么之后date命令的返回永远是这个值不会变。在一般情况下项目给出了@%Y-%m-%d %X这样的FAKETIME设置形式来设置时间从一个时间点开始流逝,但是对于docker环境似乎并不适用。github上也有issue了,看怎么解决了。总结一下就是用相对时间的加加减减一些<数字><单位>如+5m,-1.5d,+20h都是可以用的。

■  关于devicemapper/mnt和容器对应关系(基于Docker 1.12)

  不是讲解devicemapper的原理… 但是我们知道devicemapper下的mnt目录下面有一堆散列名目录。这些目录往往都一对一地对应着某个容器/镜像的文件系统结构。

  那么怎么把通过这个散列找到对应容器呢?

  其实可以查看docker inspect 某个容器的信息中的GraphDriver.Data.DeviceName,后面有一串所谓的pool名,就是这个散列值。找出对应的就好了。如果嫌散列值比较难看的话也可以在devicemapper/metadata中找到对应散列值的json配置文件,里面标注了device_id,和GraphDriver.Data.DeviceId一致的就是了。

■  关于aufs、devicemapper和overlay 区别的简单理解

  之前一直没注意到,其实docker在将容器/镜像内容存储到宿主机这一方面存在多种方式。每种方式对应这一种存储驱动。副标题中的aufs, devicemapper, overlay都是一种驱动方式而已。三者是按照从旧到新的顺序写出来的。aufs这种驱动在centos6上就已经存在了,最为古老;devicemapper常见于centos7上,通过epelyum源直接安装的docker采用的就是这种驱动;overlay比较新,也常用于centos7上。

  说到三者的特点,overlay驱动最为优化。采取overlay驱动的容器/镜像相关数据保存在docker根目录(通常是/var/lib/docker)的overlay目录下。这个目录下有很多经过点窜的目录名,代表的是一个个文件系统层。对于容器层的每个目录下都有lowerid记录着它下一层的数据的ID,还有就是upper目录记录的是这一层中做出的文件的新增和改变的情况。overlay的一个重要特点就是容器内外文件的完全同步。如果在容器中删除掉一些新增的文件,那么在相应的容器的upper目录下面,这些文件也会被删除,因此可以实时释放宿主机的磁盘空间。  * 但是需要注意,不应该在宿主机中直接对upper目录中的内容进行删除。容器中看到的是其实是merged视图(综合了lowerdir和upperdir两个文件系统层的内容),其中通过image层直接引用或者container层覆盖了image层 or container层自有的文件,这些文件在容器里显示的inode和在宿主机相应点窜目录中查看inode一致,如图所示:

  但是在overlay文件系统中,似乎存在这样一种机制。从merged视图中发起的删除,会将文件对应block需要删除标记告知给宿主机文件系统,因此容器中删除文件会直接释放宿主机的磁盘空间。但是宿主机中删除某个文件,无从告知容器中的文件系统(想想也是,宿主机里有那么多和容器无关的文件,很难做到告知),导致容器中会认为,原先文件对应的block块已经没有了inode的引用,但是又不能释放,此时会出现一些异常现象。比如一个文件明明ls看不到,但touch一下也不会出现,程序显示写入文件正常,但是又无从看到写入的内容等等。

  【overlay文件系统说明 https://www.jianshu.com/p/959e8e3da4b2】

  相比之下,devicemapper驱动是类似于数据库的数据文件那样,首先在系统中创建一个可扩容的数据文件data用来保存容器/镜像数据,这个文件的最大大小默认通常是100G,位于docker根目录devicemapper/devicemapper/中。这个目录下还有metadata文件。之后所有的容器/镜像实质内容数据都是被写入到data和metadata两个文件中的,其他的一些配置和相关的内容可能会存放在devicemapper目录下的其他地方。devicemapper驱动的一个不好的地方就是无法实时地将宿主机的磁盘空间释放出来(也是我上面提到过的)。因为数据增加之后data文件扩大,但是将容器内的内容删除之后data文件不会自动缩回原来的大小。相当于整个data文件只会变大不会变小直到达到指定的最大大小,除非在这个过程中进行docker服务的重启或者容器的删除重建。

  aufs驱动现在用的已经不多了,主要是centos6通过yum安装docker-io的时候会用到这种驱动。在/var/lib/docker/aufs中会有diff,layers,mnt三个目录。layers目录保存了一些以层ID命名的文件,其中记录了这个层的下面有哪些层作为基础。diff目录下则是一些以层ID命名的子目录,每个目录下是本层针对所有基础层所作出的变化。私以为aufs比较好理解,因为它把包括一个容器对应的镜像的所有层,再加上容器本身的读写层都原原本本地展示出来,理解docker原理的人可以很轻松的根据层级去寻找自己想要的信息。mnt目录下则是各个容器根目录的挂载点,容器层ID为名的那个子目录下面的内容就是和容器中根目录完全对应的。

【Docker】 积累的更多相关文章

  1. docker搭建环境积累

    weblogic12搭建 sudo docker pull ismaleiva90/weblogic12 sudo docker run -d -p : -p : ismaleiva90/weblog ...

  2. 开发漫谈:千万别说你不了解Docker!

    1dotCloud到Docker:低调奢华有内涵   写在前面:放在两年前,你不认识Docker情有可原.但如果现在你还这么说,不好意思,我只能说你OUT了.你最好马上get起来,因为有可能你们公司很 ...

  3. 程序猿,千万别说你不了解Docker!

    放在两年前,你不认识Docker情有可原.但如果现在你还这么说,不好意思,我只能说你OUT了.你最好马上get起来,因为有可能你们公司很快就会引入Docker. 今天就和大家讨论讨论这个备受好评的应用 ...

  4. Docker学习笔记整理

    Docker接触有一段时间了,但是对于Docker的使用可以说是一点不会.现在要在Docker上部署基于Angular开发的页面.只能一点点积累查找的资料,顺手整理一下,方便后面的回顾. 其中用到的资 ...

  5. Docker在云环境中的应用实践初探:优势、局限性与效能评测

    作者 商之狄 发布于 2014年11月10日 本文依据笔者所在团队的一些近期开发和应用的实践,整理出一些有意义的信息,拿出来和社区分享.其中既包括在云端应用Docker与相关技术的讨论,同时也有实施过 ...

  6. 什么是 docker?

    关于 Docker 是什么,有个著名的隐喻:集装箱.但是它却起了个“码头工人”( docker 的英文翻译)的名字.这无疑给使用者很多暗示:“快来用吧!用了 Docker ,就像世界出现了集装箱,这样 ...

  7. Windows Container 和 Docker:你需要知道的5件事

    微软在2016年的Ignite技术大会上正式发布了Windows Server 2016,其中的容器服务已经可以作为生产环境使用.这意味着Windows 内置的容器服务正式进入了大家的视野,虽然之前我 ...

  8. 生产环境中使用Docker Swarm的一些建议

    译者按: 实践中会发现,生产环境中使用单个Docker节点是远远不够的,搭建Docker集群势在必行.然而,面对Kubernetes, Mesos以及Swarm等众多容器集群系统,我们该如何选择呢?它 ...

  9. 升级项目到.NET Core 2.0,在Linux上安装Docker,并成功部署

    概述 容器,顾名思义是用来存放并容纳东西的器皿: 而容器技术伴着Docker的兴起也渐渐的映入大家的眼帘,它是一个抽象的概念,同时也是默默存在世上多年的技术,不仅能使应用程序间完全的隔离,而且还能在共 ...

随机推荐

  1. 【Unity3D】Unity3D开发《我的世界》之一、创建一个面

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/unity_minecraft_01.html 最近总有人问及我的游戏里跟<我的世界>一样的地形是如何实 ...

  2. FusionCharts 2D柱状图和折线图的组合图

    1.设计思路 (1)了解组合图的特性以及用法,选用图的类型: (2)设计出两根柱子和两根折线,分开展示. 2.设计步骤 (1)设计页面 Column2DLine.html: <!DOCTYPE ...

  3. 将搜狗词库(.scel格式)转化为txt格式

    参考:http://blog.csdn.net/zhangzhenhu/article/details/7014271 #!/usr/bin/python # -*- coding: utf-8 -* ...

  4. VTK显示mhd,mha格式文件

    下一篇文章将详细介绍mhd,mha文件的构成以及如何制作void renderMhd () { // read input image vtkSmartPointer<vtkMetaImageR ...

  5. Scheme change not implemented

    1.错误描述 2.错误原因 由于在改变Java代码中的方法或运行代码出现,导致Tomcat编译的代码不能替换工作空间的代码,即不能及时同步,出现错误 3.解决办法 (1)关闭Tomcat,clean一 ...

  6. 双硬盘RAID 0全攻略

    . RAID53 RAID7即高效数据传送磁盘结构,是RAID3和带区结构的统一,因此它速度比较快,也有容错功能.但价格十分高,不易于实现. 为什么需要磁盘阵列        如何增加磁盘的存取(ac ...

  7. CSS开启硬件加速提高网站性能

    国外一篇文章,有点意思,转载过来,准备尝试下~ 中文地址:http://www.cnblogs.com/yzw7489757/ 原文地址:http://blog.teamtreehouse.com/i ...

  8. 已在Terminal安装了包,PyCharm却提示无法找到

    想使用python的dpkt包解析pcap文件进行分析,已经按照提示在终端输入sudo apt install python-dpkt,并且显示安装成功. 但是回到PyCharm中依然报错,如图所示: ...

  9. 省市区/国籍 多级联动-jq

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 洛谷P3796 【模板】AC自动机(加强版)(AC自动机)

    洛谷题目传送门 先膜一发yyb巨佬 orz 想学ac自动机的话,推荐一下yyb巨佬的博客,本蒟蒻也是从那里开始学的. 思路分析 裸的AC自动机,这里就不讲了.主要是这题太卡时了,尽管时限放的很大了.. ...