Docker踩坑四个教训 - resurface


我们依赖 Docker,它是我们最喜欢的技术之一。但是将 Docker 用于商业软件显示了我们发现困难的一些粗糙边缘。
 
1. “latest”标签
我们不是第一个意识到最新标签存在重大问题的人,但我们一开始真的没有看到这些问题。我们现在走另一条路,从我们的 Docker 镜像中删除了我们的“latest”标签。有几件事让我们处于边缘。
“latest”模式扭曲或破坏了每个 CDN 想做的缓存类型,因为随着时间的推移,这会导致多个具有相同名称但内容不同的工件。CDN 真正喜欢的是具有唯一版本号的不可变工件。真正可怕的是,如果最新标签由于这种缓存而失败,您将永远不会知道。
“latest”的另一个疯狂之处在于,用户很难找到实际的版本号。假设您使用特定版本名称和“latest”标签发布图像。安装后docker images,即使安装了较新版本的容器,输出也将显示“latest”而不是版本号。那么用户应该如何确定实际安装了哪些版本呢?通过回退到比较图像 id 哈希值,这是对人们时间的疯狂利用。
 
2. Docker的缓存很致命
Docker 镜像是分层构建的,Docker 积极地缓存这些层以避免下载未更改的位。问题是这种缓存基于 Dockerfile 中的脚本文本,而不是这些脚本的实际结果。
使用--no-cache指令很容易解决这个问题
 
3. 为多个进程设计是很棘手
Docker 支持每个容器都有一个它执行的单个命令的想法。这对于简单的情况非常有用,但假设您有三个一起运行的轻量级服务。有些人会争辩说,这应该始终分解为三个独立的容器,但这并非没有成本。现在,您需要构建/管理/版本的组件数量增加了 3 倍,并且这些过程如何相互交互受到更多限制,因为它们是完全独立的。
我们将我们的服务放在一起,并在作为容器的主要控制点的supervisord上进行标准化。这使我们可以放心地在单个容器包中运行多个服务,而无需编写任何自定义脚本。
 
4.较小的容器并不总是更快
很多采用Docker 理由是 Docker 容器将比它们所取代的传统虚拟机小得多,开销也更少。您不必运行额外的 Ubuntu 副本,而是拥有一个很小的容器!不幸的是,这远不能保证。
还有一个神话,即 Alpine 作为最明显的小发行版,普遍优于其他发行版。它很小,所以它必须更快,对吧?不必要!
我们在 Alpine 上看到了在 RedHat 或 Ubuntu 上没有看到的显着性能下降,因为 Alpine 不是基于 glibc。最终,我们决定花费额外的时间和精力来调整我们在 Alpine 上的配置是值得的,以获得尽可能小的下载大小。但这是一项重大的时间投资,一开始并不明显如何去做。
Docker 使构建非常小的高性能容器成为可能,但简化性能和下载大小的大部分负担仍然落在容器开发人员身上。基于用于开发的相同发行版发布多 GB 映像非常容易。获得轻量级图像仍然需要技巧和细心。