三个技巧,将Docker镜像体积减小90%(2)

你可以继续使用与上面相同的Dockerfile,只是现在要调用两次:

FROM node:8 as build WORKDIR /app COPY package.json index.js ./ RUN npm install FROM node:8 COPY --from=build /app / EXPOSE 3000 CMD ["index.js"]

Dockerfile的第一部分创建了三个层,然后这些层被合并并复制到第二个阶段。在第二阶段,镜像顶部又添加了额外的两个层,所以总共是三个层。

三个技巧,将Docker镜像体积减小90%

现在来验证一下。首先,构建容器:

$ docker build -t node-multi-stage .

查看镜像的历史:

$ docker history node-multi-stage IMAGE CREATED BY SIZE 331b81a245b1 /bin/sh -c #(nop) CMD ["index.js"] 0B bdfc932314af /bin/sh -c #(nop) EXPOSE 3000 0B f8992f6c62a6 /bin/sh -c #(nop) COPY dir:e2b57dff89be62f77… 1.62MB b87c2ad8344d /bin/sh -c #(nop) CMD ["node"] 0B <missing> /bin/sh -c set -ex && for key in 6A010… 4.17MB <missing> /bin/sh -c #(nop) ENV YARN_VERSION=1.3.2 0B <missing> /bin/sh -c ARCH= && dpkgArch="$(dpkg --print… 56.9MB <missing> /bin/sh -c #(nop) ENV NODE_VERSION=8.9.4 0B <missing> /bin/sh -c set -ex && for key in 94AE3… 129kB <missing> /bin/sh -c groupadd --gid 1000 node && use… 335kB <missing> /bin/sh -c set -ex; apt-get update; apt-ge… 324MB <missing> /bin/sh -c apt-get update && apt-get install… 123MB <missing> /bin/sh -c set -ex; if ! command -v gpg > /… 0B <missing> /bin/sh -c apt-get update && apt-get install… 44.6MB <missing> /bin/sh -c #(nop) CMD ["bash"] 0B <missing> /bin/sh -c #(nop) ADD file:1dd78a123212328bd… 123MB

文件大小是否已发生改变?

$ docker images | grep node- node-multi-stage 331b81a245b1 678MB node-vanilla 075d229d3f48 679MB

最后一个镜像(node-multi-stage)更小一些。

你已经将镜像的体积减小了,即使它已经是一个很小的应用程序。

但整个镜像仍然很大!

有什么办法可以让它变得更小吗?

2. 用distroless去除容器中所有不必要的东西

这个镜像包含了Node.js以及yarn、npm、bash和其他的二进制文件。因为它也是基于Ubuntu的,所以你等于拥有了一个完整的操作系统,其中包括所有的小型二进制文件和实用程序。

但在运行容器时是不需要这些东西的,你需要的只是Node.js。

Docker容器应该只包含一个进程以及用于运行这个进程所需的最少的文件,你不需要整个操作系统。

实际上,你可以删除Node.js之外的所有内容。

但要怎么做?

所幸的是,谷歌为我们提供了distroless

以下是distroless存储库的描述:

“distroless”镜像只包含应用程序及其运行时依赖项,不包含程序包管理器、shell以及在标准Linux发行版中可以找到的任何其他程序。

这正是你所需要的!

你可以对Dockerfile进行调整,以利用新的基础镜像,如下所示:

FROM node:8 as build WORKDIR /app COPY package.json index.js ./ RUN npm install FROM gcr.io/distroless/nodejs COPY --from=build /app / EXPOSE 3000 CMD ["index.js"]

你可以像往常一样编译镜像:

$ docker build -t node-distroless .

这个镜像应该能正常运行。要验证它,可以像这样运行容器:

$ docker run -p 3000:3000 -ti --rm --init node-distroless

现在可以访问:3000页面。

不包含其他额外二进制文件的镜像是不是小多了?

$ docker images | grep node-distroless node-distroless 7b4db3b7f1e5 76.7MB

只有76.7MB!

比之前的镜像小了600MB!

但在使用distroless时有一些事项需要注意。

当容器在运行时,如果你想要检查它,可以使用以下命令attach到正在运行的容器上:

$ docker exec -ti <insert_docker_id> bash

attach到正在运行的容器并运行bash命令就像是建立了一个SSH会话一样。

但distroless版本是原始操作系统的精简版,没有了额外的二进制文件,所以容器里没有shell!

在没有shell的情况下,如何attach到正在运行的容器呢?

答案是,你做不到。这既是个坏消息,也是个好消息。

之所以说是坏消息,因为你只能在容器中执行二进制文件。你可以运行的唯一的二进制文件是Node.js:

$ docker exec -ti <insert_docker_id> node

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/12581.html