Wayfair的Python平台团队维护了一组基本Docker镜像,供所有已部署的Python应用程序使用。维护这些基础图像使我们能够:

  • 规范我们的环境(我们所有的图像都基于CentOS)
  • 简化部署的应用程序开发者(图片船舶预配置连接到我们内部的PyPI和RPM镜)
  • 提高安全性(我们将采取措施,将被部署到生产硬化图像)。

我们最近重构了我们的图像,使它们更有效减少我们的图像大小超过50%。这些改进不仅是开发者友好的优化:除了减少图像生成时间和存储需求,许多优化使图像更安全,因为降低了图像的复杂性降低了整体的攻击面。请仔细阅读,看看我们如何实现这个伟大的结果。

优化工具

我们使用和推荐潜水个人资料图片。它提供了一个图形化的界面快速探索图像层并计算“效率得分”与浪费的空间亮点图像。

以下是图像的例子潜水报告centos: centos7,其类似于在Wayfair所使用的基础的CentOS图像。

相比较而言,这里是潜水输出为我们在CentOS 7.5上运行的Python 3.8未优化的基础映像之一:高达931MB(作为比较的基础,开源软件的总规模python: 3.8.5图像是882MB)。

继承自CentOS基础图像的层用黄色高亮显示,而在Python图像中引入的最大层用红色高亮显示。Dive显示生成所选层的命令(以白色突出显示)。

要优化我们的形象,我们通过每个大层的阶梯,以识别那些可以消除或修剪。以下是图像的最优化形式的潜水报告。

下面的优化,最终的图像414MB,减少了超过50%的!我们通过以下策略实现了这一减少。

优化策略

当安装包时,清理在同一层

上面的未优化的图像中的最大层是和324MB从命令导致百胜-y安装的libcurl。该层是如此之大是因为荫命令生成高速缓存,引入显著cruft的。

因此,在运行yum install时,最好在一个命令中安装所有包,并始终在同一步骤中删除缓存。

从CentOS的:centos7#避免这种运行yum安装-y富运行yum安装-y酒吧#更好,但仍然很糟糕运行yum安装-y \富\酒吧#首选此运行yum安装-y \富\酒吧\ &&百胜干净所有\ &&室射频的/ var /缓存/百胜

通过更新命令安装libcurl && yum clean all && rm -rf /var/cache/yum中,该层尺寸为324MB降低到23MB,减少93%

同样的原则也适用于其他语言的包管理器;大多数都针对尺寸敏感的Docker图像的本地开发进行了优化。始终尝试在一个步骤中安装所有包,并禁用包管理器的缓存。例如:

在构建或编译代码时使用多级构建

我们从源代码编译包含在基本映像中的Python发行版,这需要许多构建依赖项。总的来说,这些依赖项超过200MB,并且只在编译时使用。建立多级防止运送最终图像中,提高图像的尺寸并降低了由航运GNU工具链和部署映像其他二进制文件出台的攻击向量这些依赖性。

取而代之的是:

在Python-基础映像:3.8.5#安装一些必要的构建Python包系统的依赖性运行yum安装-y \ GCC \ &&百胜清洁所有\ &&室射频的/ var /缓存/百胜COPY requirements.txt。RUN PIP安装-r requirements.txt COPY应用程序代码/。入口点[ “蟒”] CMD [ “script.py”]

喜欢这个:

在Python-基础映像:3.8.5 AS建设者#安装了一些系统构建Python包运行yum安装依赖必要-y \ GCC \ &&百胜清洁所有\ &&室射频的/ var /缓存/百胜#创建的virtualenv来一直依赖一起运行python -m VENV的/ opt / VENV ENV PATH = “/选择/ VENV /斌:$ PATH” #安装依附到虚拟环境COPY requirements.txt。RUN PIP安装-r requirements.txt蟒蛇基图像:3.8.5#copy过来唯一的virtualenv COPY --from =建设者的/ opt / VENV的/ opt / VENV ENV PATH =“/选择/ VENV /斌:$ PATH“COPY应用代码/。入口点[ “蟒”] CMD [ “script.py”]

使用泊坞窗图像的virtualenv如上面的例子似乎违反直觉因为搬运工人容器本身孤立的,而是他们在使其易于所有的Python依赖复制构建阶段之间有用。小心使用这种方法时,pip安装荷兰国际集团与动态链接的依赖关系的软件包(例如,其中包装依赖于不与所述包本身捆绑一个C库),因为这些依赖关系还必须安装在最终图像中,不只是在中间构建步骤。

避免运行chmodRUN CHOWN步骤

当执行更改文件权限或文件所有权的命令时,Docker会创建该文件或目录的副本。这可能会导致严重的膨胀。避免这种情况发生,乔恩荷兰国际集团在同一步骤中的内容被复制到图像:

FROM centos的:centos7#不这样做COPY ./ /应用RUN CHOWN -R 1001:100 /应用程序#首选此COPY --chown = 1001:100 ./ /应用

码头工人了近期实施一个修改文件权限选项复制,但它是唯一可用的当Buildkit后端启用。在使用传统构建后端时,要么在文件复制到映像之前设置权限模式,要么使用多级构建,其中修改文件权限命令仅在中间图像中的运行。

通过消除,我们能够从图像中消除185MB修改文件权限命令。

应用程序数据复制到图像前批判性的思考

我们遇到了很多dockerfiles包括复制。/。/将所有应用程序数据复制到映像中的最后步骤之一。虽然这样做很方便,但可能会导致生产映像(测试套件、文档等)中出现不必要的麻烦。

考虑包括.dockerignore文件在该项目故意被包含在最终图像中排除不必要的文件。

结论

如果您发现了这个有趣的,你可以享受约Wayfair的阅读创新的方法构建一个Python平台团队,或者听这个播客.__ init__事件有关Python在Wayfair。如果您想了解更多信息,请联络!我们是目前招聘,并一直在寻找高级Pythonistas加入我们的团队。