使用 Docker-in-Docker 来运行 CI 或集成测试环境?三思!

Docker-in-Docker 的主要目的是帮助 Docker 本身的发展。很多人用它来运行 CI 系统(例如 Jenkins ),这初看起来还不错,但会遇到很多“有趣”的问题,这些问题可以通过将 Docker socket 绑定安装进 Jenkins 容器中解决。

让我们来看看这是什么意思。如果你只是想要快速解决方案而不是细节,可以直接访问我们的官网希云—— Docker 私有云领导者!

Docker-in-Docker:优点

两年多前,我为-privileged flag in Docker贡献了代码并写了first version of dind。目的是为了帮助核心团队更快速地进行 Docker 开发。在 Docker-in-Docker 之前,典型的开发流程是:

hackity hack

构建

停止正在运行的 Docker 进程

运行新的 Docker 进程

测试

重复

如果你想要一个良好可复用的构建(例如在一个容器中),稍微有一点复杂:

ackity hack

确认有一个可工作版本的 Docker 在运行

使用旧 Docker 构建新 Docker

停止 Docker 进程

启动新的 Docker 进程

测试

停止新的 Docker 进程

重复

随着 Docker-in-Docker 的到来,这个过程简化为:

hackity hack

一步构建和运行

重复

好多了,不是么?

Docker-in-Docker:缺点

然而,出乎人们的预料,Docker-in-Docker 不是百分之百完美和健壮。我的意思是,有几个问题需要注意。

一是关于 LSM(Linux Security Modules)比如 AppArmor 和 SELinux:当启动一个容器,那个“内部 Docker ”可能尝试应用安全配置文件并导致“外部Docker”产生混乱或者冲突。当你尝试去合并带有-privileged参数的原始实现的时候这可能是最难解决的问题。我的修改在我的 Debinan 机器和 Ubuntu 测试虚拟机上可以运行(并且所有的测试都通过了),但在 Michael Crosby 的机器上(我没记错的话是 Fedora )却功败垂成。我不记得问题的具体原因,但是这可能是由于 Mike 是个聪明的家伙,在SELINUX=enforce(我在使用 AppArmor )的情形下运行而我的修改没有将 SELinux 考虑在内。

Docker-in-Docker:丑陋

第二个问题和存储驱动有关,当你在 Docker 中运行 Docker 时,外部的 Docker 运行在正常的文件系统( EXT4、BTRFS 等等你有的)之上而内部 Docker 运行在写时复制的系统(AUFS、BTRFS、Device Mapper,依赖于外层 Docker 所使用的文件系统)之上。有许多组合不能工作。例如,你不能在 AUFS 之上运行 AUFS。如果你在 BTRFS 之上运行 BTRFS,开始时会正常运行,一旦你嵌入 subvolumes,移除父级 subvolumes 会失败。Device Mapper 没有命名空间,所以如果多个 Docker 实例在一台机器上使用它,它们会看见(和影响)其它的镜像和容器备份装置。这样不好。

问题有很多解决方法;例如,如果你想在内部 Docker 中使用 AUFS,将/var/lib/docker升级为 volume 就会解决问题。 Docker 为 Device Mapper 目标名称添加了一些基础的命名空间,所以在一台机器上运行多个实例,就不会互相干扰。

目前为止,设置并不是完全一步到位,你可以看在 GitHub 的dind仓库中的这几个 issues。

Docker-in-Docker:更加糟糕

关于构建缓存?这同样相当棘手。人们经常问我,“我在运行 Docker-in-Docker,怎么样我才能使用主机上的镜像而不是重新将所有东西拉入内部 Docker?”。

一些胆大的人试图从主机绑定安装/var/lib/dockerDocker-in-Docker容器中。有时候在多容器之间共享/var/lib/docker

Docker 进程明确地被设计为独占/var/lib/docker的访问。没有什么可以触碰隐藏在那里的任何文件。

为什么是这样?这是从使用 dotClound 的时候开始的惨痛教训。 dotCloud 容器引擎工作于多进程同时访问/var/lib/dotcloud。像原子文件替换(代替编辑)这样的小窍门将代码强制锁定,其它 safe-ish 系统的实验就像 SQLite 和 BDB ,当我们重构我们的容器引擎(最终成为 Docker ),一个大的设计决策是收集一个单一进程的所有的容器操作和所有的并发访问。

(不要误会我的意思:完全有可能做一些漂亮的、可靠的和快速的涉及多个进程和先进的并发管理,但我们认为 Docker 的单一角色模型更简单,以及更容易编写和维护)

这意味着,如果你在多 Docker 实例之间共享/var/lib/docker目录,你会碰到许多问题。当然,它可能工作,尤其是在早期的测试。 “看,我可以在 Ubuntu 中运行Docker!”。但是,尝试做一些更复杂(从两个不同的实例拉相同的镜像)的操作,世界就会燃烧起来。

这意味着,如果你的 CI 系统进行构建和重建,每一次你会重新启动 Docker-in-Docker 容器,你可能会摧毁它的缓存。这真的不好。

解决方案

让我们退一步,你真的想要 Docker-in-Docker?或者当 CI 系统本身就是一个容器的时候你只是想要在 CI 系统中运行 Docker(具体为:构建、运行,有时 push 容器和镜像)。

我敢打赌,大多数人只是想要后者。你想要的一个解决方案是使得你的像 Jenkins 一样的 CI 系统能够启动容器。

最简单的方法就是通过使用-v参数帮顶安装它来为你的 CI 系统暴露 Docker 的 socket。

简单的来说,当你启动你的 CI 容器( Jenkins 或者其他),而不是使用 Docker-in-Docker 来 hacking 一些东西,用这条命令启动它:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

现在这个容器将能够访问 Docker Socket,然后就能启动容器。它将启动“兄弟”容器而不是“子”容器。

如果你的 CI 使用 Docker 二进制脚本,你可以将它包含在你的 CI 镜像中或者从主机 bind-mount。例如:

docker run -v /var/run/docker.sock:/var/run/docker.sock \ -v $(which docker):/bin/docker \

-ti ubuntu

这看起来就像 Docker-in-Docker,感觉起来也像 Docker—in-Docker,但它不是 Docker-in-Docker :当你的CI容器要创建更多容器时,这些容器将会在顶级 Docker 中被创建。你将不会与遇到嵌入的影响,构建缓存也将在多实例中共享。

总结

希云认为:未知的世界总是充满探索的欲望,即便深层级的使用将会碰到不可预知的错误,但我们依然努力向前。Docker-in-Docker 的确有很多优点,但同时不可避免肯定还有需要完善的地方。在合适的场景下使用 Docker-in-Docker 将会带来方便,但是使用 Docker-in-Docker 来运行 CI 或集成测试环境将会遇到一些困难,不妨尝试上文所提出的解决方案。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容