作者丨Pavan Kumar
译者 | 崔莹峰
策划丨诺亚
编写Dockerfile看起来很容易,除非你最终编写了大小为0.5GB的Docker镜像。是的,没错。我最近在做一个ReactJS项目,在那里我正在构建一个前端应用程序。React JS项目没有什么新鲜的。我使用了与典型前端应用程序相同的package.json,相同的依赖集。现在,我决定将应用程序迁移到Kubernetes。所以我将Docker镜像推送到DockerHub并尝试在Kubernetes部署Pod。
我使用的是一个本地集群,Pod花了5分零7秒启动。我很惊讶。然后我将其部署到AKS集群(Azure Kubernetes集群)。令人惊讶的是,它花了3分40秒。这可是件大事。我尝试对Pod进行压测以触发Kubernetes HPA(Horizontal Pod Autoscaler)。新的Pod需要同样的3分钟才能出现,最终应用程序被太多的请求淹没,不堪重负以致崩溃不断重启。经过调查,我发现镜像的大小是瓶颈,当然,你不会想要如此巨大的Docker镜像(0.5GB)。那时我意识到我必须对Docker镜像大小做些什么。因此,我使用了Docker多阶段构建的概念。
Docker构建:
这是我最初的一个Dockerfile,它是为一个典型的ReactJS应用程序提供的。如果你打开查看,你就可以看到第一行代码,我使用了node:alpine作为基础镜像,如下是镜像构建完成后的尺寸。
非多阶段构建
这是构建镜像的典型方法,编写这样的Docker文件似乎很容易。但是从Kubernetes的角度来看,使用这种方法存在一些缺点如下
a)镜像的大小直接影响Pod启动时间。
b)镜像越小,Pod启动越快。
Docker多阶段构建:
Dockerfile中的多阶段构建特性使你能够创建具有更好缓存和占用更小安全空间的较小容器镜像。使用多阶段构建,你可以在Dockerfile中使用多个FROM语句。每个FROM指令可以使用不同的基础镜像,并且每个FROM指令都会开始构建一个新的阶段。你可以有选择地将一个阶段构建好的内容复制到另一个阶段,对于那些不需要出现在在最终镜像里的内容就留在上一个阶段好了。
似乎不一样?好吧,让我们了解一下这个文件。
第一行称为阶段。这些阶段没有命名,你通过它们的整数来引用它们,从0开始表示第一条FROM指令。或者,你也可以通过向FROM指令添加AS来命名阶段。
然后其余的步骤保持不变。改变游戏规则的一个步骤是COPY——来自(第18行)。使用多阶段生成时,可以在Docker文件中使用多个FROM语句。每个FROM指令都可以使用不同的基础镜像,并且每个指令都开始构建一个新的阶段。你可以有选择地将一个阶段构建好的内容复制到另一个阶段,对于那些不需要出现在在最终镜像里的内容就留在上一个阶段好了。
现在让我们开始构建镜像。
多阶段构建镜像尺寸
哇,是的!图像大小压缩了95%。图像大小现在是27.2MB。
我的本地集群花了25秒来拉取镜像并开始使用。我的AKS集群花了10秒钟来拉取镜像并开始使用。
这就是如何利用Docker中的多阶段构建来压缩Docker镜像的大小。
原文链接:
https://levelup.gitconnected.com/how-i-reduced-the-size-of-my-docker-image-by-95-520a05439300
译者简介
崔莹峰,51CTO社区编辑,一名70后程序员,拥有10多年工作经验,长期从事 Java开发,架构设计,容器化等相关工作。