[在创建 Carbon.now.sh 的离线版本时减少 Docker 的镜像大小](https://res.cloudinary.com/practicaldev/image/fetch/s--qMon73PF--/c_limit%2Cf_auto%2Cfl_progressive %2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1532344859118-9b9581911b87%3Fixlib%3Drb-1.2.1%26q%3D80%26fm%3Djpg%26crop%3Dentropy%26cs%3Dtinysrgb%26w%3D1080%26fit %3Dmax%26ixid%3DeyJhcHBfaWQiOjExNzczfQ)

免责声明:这接近我第一次使用 Docker,所以你可能会觉得这篇文章没有给人留下深刻的印象 :)。

我敢肯定,你们中的大多数人已经习惯了在演示文稿或会议演讲中看到的那些漂亮的代码片段。它们看起来就像这样:

[在创建 Carbon.now.sh 的离线版本时减少 Docker 的图像大小](https://res.cloudinary.com/practicaldev/image/fetch/s--typTMLrV--/c_limit%2Cf_auto%2Cfl_progressive %2Cq_auto%2Cw_880/https://lengrand.fr/content/images/2020/05/image.png)

代码片段示例

好吧,几乎所有这些都来自carbon.now.sh,他在使您的代码看起来不错方面做得很好。

不幸的是,我在一家大公司工作,它决定阻止访问该网站以避免任何数据泄露的风险(如果你问我,这很有意义)。好吧,对我们来说幸运的是 Carbon 是开源并使用MIT 许可证所以我们可以旋转我们自己的内部版本。

此博客列出了我对应用程序进行 docker 化并减小最终图像大小的过程。

让甜蜜的 Docker 映像工作

第一步是让任何类型的 Docker 镜像正常工作,直截了当。我们开始做吧。

我们首先克隆 repo 并在项目的根目录创建一个Dockerfile。该项目需要节点 12,所以我们将使用官方节点镜像作为基础镜像。

FROM node:12

WORKDIR /app

COPY package*.json ./
RUN yarn install
COPY . .
RUN yarn build

CMD ["yarn", "start"] 

进入全屏模式 退出全屏模式

我们在这里所做的非常有限:

  • 我们在基础镜像中定义了一个工作目录

  • 我们使用yarn install安装依赖项

  • 我们建项目

  • 我们将yarn start定义为运行映像时的启动命令

现在剩下要做的实际上是构建映像并对其进行测试(如果您打算长时间运行服务器,您可能希望使用-d选项来获得分离模式:)。我只是在这里测试)。

$ docker build -t julienlengrand/carbon.now.sh .
$ docker run -p 3000:3000 julienlengrand/carbon.now.sh:latest

进入全屏模式 退出全屏模式

现在如果我们去http:localhost:3000,我们应该看到这个:

[在创建 Carbon.now.sh 的离线版本时减少 Docker 的图像大小](https://res.cloudinary.com/practicaldev/image/fetch/s--jipw_8qb--/c_limit%2Cf_auto%2Cfl_progressive %2Cq_auto%2Cw_880/https://lengrand.fr/content/images/2020/05/image-1.png)

carbon的登陆页面,但是在本地主机上

伟大的!!!! .... 除了我的图像占用 2.34Gb 磁盘空间的事实! 对于截屏的东西,它是不可接受的:)。

➜ carbon git:(feature/docker) docker images
REPOSITORY IMAGE ID SIZE
julienlengrand/carbon.now.sh 81f97ac3419b 2.43GB

进入全屏模式 退出全屏模式

让我们看看我们还能做些什么。

仅保留图像中的应用程序

问题是,我们现在构建图像的方式有效,但它远非高效(但我们已经知道了)。我们在容器中拥有整个工具链,以及构建和开发依赖项等等。我们想摆脱这一切,因为我们不需要它来运行我们的服务器。

在 Docker 世界中执行此操作的一种常见方法称为多步构建,实现此目的的方法之一是使用构建器模式(不要与其他众所周知的构建器模式相混淆)。简而言之,我们使用第一个容器来构建我们的应用程序并创建我们的最终图像。

让我们看看它是什么样子的:

FROM node:12 AS builder

WORKDIR /app
COPY package*.json ./
RUN yarn install
COPY . .
RUN yarn build

FROM node:12

WORKDIR /app
COPY --from=builder /app .
EXPOSE 3000
CMD ["yarn", "start"]

进入全屏模式 退出全屏模式

此 Dockerfile 包含与之前基本相同的行,但有两个主要区别:

  • 我们现在将操作拆分到 2 个容器上(一个构建,另一个将运行)

  • 我们将构建步骤的结果复制到第二个容器以创建最终映像。

就像以前一样,我们使用相同的命令来运行和测试这个新版本(令人惊讶的是,它按预期工作!)。

可以直接看到多步骤构建的良好副作用。我们将最终图像大小除以 2:

➜ carbon git:(feature/docker) docker images
REPOSITORY IMAGE ID SIZE
julienlengrand/carbon.now.sh 586a65d1ee4e 1.34GB

进入全屏模式 退出全屏模式

1.34Gb 对于一个需要美化截图的 web 应用程序来说,这对我来说仍然太多了。让我们进一步深入。

使用更高效的图像

使用官方的 Node 镜像有好处,但考虑到它基于 Debian 系统,它也非常大。我们的下一步是查看较小的图像。众所周知的“轻量级”容器发行版之一是alpine,幸运的是,它有一个受支持的节点版本,称为mhart/alpine-node!

这次我们的 Dockerfile 几乎没有变化,我们只是想替换基础镜像:

FROM mhart/alpine-node:12 AS builder

WORKDIR /app
COPY package*.json ./
RUN yarn install
COPY . .
RUN yarn build

FROM mhart/alpine-node:12

WORKDIR /app
COPY --from=builder /app .
EXPOSE 3000
CMD ["yarn", "start"]

进入全屏模式 退出全屏模式

再一次,我们以预期的成功构建和运行:)。

同样,我们将图像大小除以 2,而这个版本的大小刚刚超过 500Mb!

➜ carbon git:(feature/docker) docker images
REPOSITORY IMAGE ID SIZE
julienlengrand/carbon.now.sh b79dbcd33de0 502MB

进入全屏模式 退出全屏模式

移除更多的依赖和我们不使用的东西

我们可以继续尝试通过向容器发送更少的代码来减小包的大小。让我们为此使用npm prune(不幸的是,yarn决定不提供完全相同的)。通过在构建后立即使用npm prune --production,我们可以摆脱所有开发依赖项。重建图像会再减少 100Mb。

这是我们最终的 Dockerfile:

FROM mhart/alpine-node:12 AS builder

WORKDIR /app
COPY package*.json ./
RUN yarn install
COPY . .
RUN yarn build
RUN npm prune --production

FROM mhart/alpine-node:12

WORKDIR /app
COPY --from=builder /app .
EXPOSE 3000
# Running the app
CMD ["yarn", "start"]

进入全屏模式 退出全屏模式

现在就是这样。我正在寻找更多方法来减少更多兆字节,但我们确实将可部署的大小减少了近 10 倍!为了让您感觉良好,以下是我们创建的图像列表,以便我们查看进度:

[在创建 Carbon.now.sh 的离线版本时减少 Docker 的图像大小](https://res.cloudinary.com/practicaldev/image/fetch/s--JtRBd2qD--/c_limit%2Cf_auto%2Cfl_progressive %2Cq_auto%2Cw_880/https://lengrand.fr/content/images/2020/05/image-2.png)

所有图像和尺寸的列表

今天,一个简单的网站需要 400Mb 才能运行,我仍然觉得很疯狂,我相信我们可以做得更好:)。但是让我们暂时停在那里,是时候度过一个当之无愧的周末了!

哦,如果你想在本地使用 Carbon,请随意从 Docker Hub 拉取镜像并在本地运行它:

docker run -p 3000:3000 julienlengrand/carbon.now.sh:latest

进入全屏模式 退出全屏模式

我今天使用的一些参考资料(感谢他们!)

[1]https://medium.com/@khwsc1/a-simple-react-next-js-app-development-on-docker-6f0bd3f78c2c

[2]https://itnext.io/frontend-dockerized-build-artifacts-with-nextjs-9463f3da3362

[3]https://medium.com/trendyol-tech/how-we-reduce-node-docker-image-size-in-3-steps-ff2762b51d5a

Logo

云原生社区为您提供最前沿的新闻资讯和知识内容

更多推荐