形象塑造最佳实践
使用该docker image history命令,您可以看到用于在图像中创建每个图层的命令。
-
使用该
docker image history命令查看getting-started您创建的图像中的图层。$ docker image history getting-started您应该得到如下所示的输出。
IMAGE CREATED CREATED BY SIZE COMMENT a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "src/index.j… 0B f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B <missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B <missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB <missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B <missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB <missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B <missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB每条线代表图像中的一个层。这里的显示显示底部位于底部,最新层位于顶部。使用它,您还可以快速查看每层的大小,帮助诊断大图像。
-
您会注意到有几行被截断。如果添加该
--no-trunc标志,您将获得完整的输出。$ docker image history --no-trunc getting-started
现在您已经了解了分层的实际效果,接下来需要学习一个重要的课程,以帮助减少容器映像的构建时间。一旦层发生变化,所有下游层也必须重新创建。
查看您为入门应用程序创建的以下 Dockerfile。
# syntax=docker/dockerfile:1 FROM node:18-alpine WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "src/index.js"]
返回到镜像历史输出,您会看到 Dockerfile 中的每个命令都成为镜像中的一个新层。您可能还记得,当您对映像进行更改时,必须重新安装纱线依赖项。每次构建时都传递相同的依赖项没有多大意义。
要修复它,您需要重构 Dockerfile 以帮助支持依赖项的缓存。对于基于节点的应用程序,这些依赖项在文件中定义package.json。您可以先仅复制该文件,安装依赖项,然后复制其他所有内容。然后,只有在package.json.
-
更新 Dockerfile 以首先复制
package.json,安装依赖项,然后复制其他所有内容。# syntax=docker/dockerfile:1 FROM node:18-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "src/index.js"] -
.dockerignore在与 Dockerfile 相同的文件夹中创建一个包含以下内容的文件。node_modules.dockerignore文件是有选择地仅复制图像相关文件的简单方法。您可以 阅读有关此内容的更多信息。在这种情况下,node_modules应在第二步中省略该文件夹COPY,否则可能会覆盖该RUN步骤中命令创建的文件。 -
使用 构建新图像
docker build。$ docker build -t getting-started .您应该看到如下所示的输出。
[+] Building 16.1s (10/10) FINISHED => [internal] load build definition from Dockerfile => => transferring dockerfile: 175B => [internal] load .dockerignore => => transferring context: 2B => [internal] load metadata for docker.io/library/node:18-alpine => [internal] load build context => => transferring context: 53.37MB => [1/5] FROM docker.io/library/node:18-alpine => CACHED [2/5] WORKDIR /app => [3/5] COPY package.json yarn.lock ./ => [4/5] RUN yarn install --production => [5/5] COPY . . => exporting to image => => exporting layers => => writing image sha256:d6f819013566c54c50124ed94d5e66c452325327217f4f04399b45f94e37d25 => => naming to docker.io/library/getting-started -
现在,对文件进行更改
src/static/index.html。例如,将其更改<title>为“The Awesome Todo App”。 -
现在再次使用构建 Docker 映像
docker build -t getting-started .。这次,您的输出应该看起来有点不同。[+] Building 1.2s (10/10) FINISHED => [internal] load build definition from Dockerfile => => transferring dockerfile: 37B => [internal] load .dockerignore => => transferring context: 2B => [internal] load metadata for docker.io/library/node:18-alpine => [internal] load build context => => transferring context: 450.43kB => [1/5] FROM docker.io/library/node:18-alpine => CACHED [2/5] WORKDIR /app => CACHED [3/5] COPY package.json yarn.lock ./ => CACHED [4/5] RUN yarn install --production => [5/5] COPY . . => exporting to image => => exporting layers => => writing image sha256:91790c87bcb096a83c2bd4eb512bc8b134c757cda0bdee4038187f98148e2eda => => naming to docker.io/library/getting-started首先,您应该注意到构建速度要快得多。而且,您会看到有几个步骤正在使用以前缓存的图层。推送和拉取此映像及其更新也会快得多。
多阶段构建是一个非常强大的工具,可以帮助使用多个阶段来创建映像。他们有几个优点:
- 将构建时依赖项与运行时依赖项分开
- 通过仅传送应用程序需要运行的内容来减小整体图像大小
构建基于 Java 的应用程序时,需要 JDK 将源代码编译为 Java 字节码。但是,生产中不需要该 JDK。此外,您可能会使用 Maven 或 Gradle 等工具来帮助构建应用程序。您的最终图像中也不需要这些。多阶段构建有帮助。
# syntax=docker/dockerfile:1 FROM maven AS build WORKDIR /app COPY . . RUN mvn package FROM tomcat COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
在此示例中,您使用一个阶段(称为build)来使用 Maven 执行实际的 Java 构建。在第二阶段(从 开始FROM tomcat),您从该阶段复制文件build。最终图像只是创建的最后一个阶段,可以使用标志覆盖它--target。
构建 React 应用程序时,您需要一个 Node 环境来将 JS 代码(通常是 JSX)、SASS 样式表等编译为静态 HTML、JS 和 CSS。如果您不进行服务器端渲染,则您的生产构建甚至不需要 Node 环境。您可以在静态 nginx 容器中传送静态资源。
# syntax=docker/dockerfile:1 FROM node:18 AS build WORKDIR /app COPY package* yarn.lock ./ RUN yarn install COPY public ./public COPY src ./src RUN yarn run build FROM nginx:alpine COPY --from=build /app/build /usr/share/nginx/html
在前面的 Dockerfile 示例中,它使用node:18映像执行构建(最大化层缓存),然后将输出复制到 nginx 容器中。
在本节中,您学习了一些映像构建最佳实践,包括层缓存和多阶段构建。
相关信息:
在下一部分中,您将了解可用于继续学习容器的其他资源。
