前言
本节我们来讲讲在我们在构建镜像过程中不出问题, 同时使得最后所构建的镜像文件大小尽可能最小, 温馨提示: 文中大图均可点击放大查看详细信息.
缓存(cache)
Docker 的优势之一在于提供了缓存, 加速镜像迭代构建, 我们知道构建镜像使用 docker build 命令, 也就是说通过 docker build 的缓存机制实现了镜像的复用, 不仅节省镜像存储空间, 也为镜像构建节省了大量时间.
Docker 会由上至下逐步执行 Dockerfile 中的指令, 按顺序执行每个指令, 在检查每条指令时, Docker 在其缓存中查找现有的中间图像, 可能会重用而不是创建新的中间图像, 如果缓存无效, 则使其无效的指令和后续所有 Dockerfile 指令都会重新生成新的中间镜像. 一旦缓存失效, 就可以使用 Dockerfile 中的其余指令, 所以从 Dockerfile 的顶部开始, 如果基础映像 (父镜像) 已经在缓存中, 则重用. 然后继续执行下一条指令与从该基础图像导出的高速缓存中所有子镜像进较, 比较每个缓存的中间镜像以查看指令是否找到并缓存是否命中, 如果高速缓存未命中, 则高速缓存无效, 如此重复执行以上过程, 最终到达 Dockerfile 的末尾. 大多数新指令只是与中间镜像中的指令进行比较, 如果匹配, 则使用缓存副本. 比如, 当在 Dockerfile 中执行 RUN pip install -r test.txt 指令时, Docker 会在其本地缓存的中间图像中搜索相同的指令, 但是旧的和新的 test.txt 文件中的内容不会进行比较. 如果我们使用新软件包更新 test.txt 文件并使用 RUN pip install 指令希望使用新软件包名称重新运行软件包安装, 如果是这种情况可能会出现问题. 同时呢, ADD 和 COPY 与其他 Docker 指令不同, ADD 和 COPY 指令需要 Docker 查看文件中的内容以确定是否存在缓存命中, Docker 将会引用文件内容的校验和与现有中间图像中的校验和进行比较, 如果文件内容或元数据已更改, 则缓存无效.
从如上我们对 Dokcer 缓存机制的大致讲解, 若我们对指令进行了更改, 那么该指令的后续每一层可能会经常重建, 所以为了更好的利用缓存, 我们需要将可能需要更改的指令尽可能的放在比较低的位置. 当我们在构建镜像时我们可以指定参数 (--no-cache=true) 来关闭缓存. 当我们需要更新源时, 我们通过链式调用 apt-get-update 和 apt-get-install 来避免缓存丢失问题.
在 Docker 中我们可以通过命令来监控文件镜像和容器文件大小, 我们知道 docker container ls 命令查看容器列表, docker container ls -s 则可以查看容器大小, 如下:
为了查看镜像构建中中间镜像历史记录, 使用命令 docker image history imagename:tag , 为了更清晰看到镜像中每一层的内容, 我们可以使用库 https://github.com/wagoodman/dive , 比如我们上一节所构建的镜像为 webapi. 我们安装完 dive 库后, 然后查看镜像中的每一层, 通过如下命令.
- docker run --rm -it \
- -v /var/run/docker.sock:/var/run/docker.sock \
- quay.io/wagoodman/dive:latest \
- webapi:latest
文件忽略(.dockerignore)
我们知道 Docker 有两个组件: 客户端和守护进程, 当我们编写 docker 命令时, 我们使用客户端向 Docker deamon 发送命令, 该命令执行所有工作, 这里我们需要知道客户端和守护进程可以单独部署到两台独立机器上, 为了让 Docker 守护进程使用 docker build 从 Dockerfile 文件中构建映像, 客户端需要向其发送执行命令的 "上下文", 上下文基本上可以说是传递给 docker build 命令的目录中的所有文件, 使用 Dockerfile 构建时, 我们在客户端可以清楚看到发送的上下文, 例如如下:
对于大型项目而言, 上下文可能会变得非常大, 毫无疑问这将会减缓通过 Dockerfile 构建镜像的速度, 因为我们必须等待客户端将所有文件发送到守护进程. 比如在 ASP.NET Core 应用程序中, 在项目根目录下可能包含大量文件, 这些文件对于大多数 Dockerfile 构建来说都不是必需的, 比如 Git 文件或者 SVN 文件, obj,bin 等文件, 所有这些附加文件在作为上下文的一部分发送时会减慢构建速度. docker 为我们提供了解决方案, 我们可以通过在根目录中创建. dockerignore 文件来忽略不需要的文件,.dockerignore 类似于. gitignore 文件, 其中包含 Docker 与文件名匹配的模式列表, 并在制作镜像时忽略, 比如如下忽略
当我们在客户端执行 docker build 命令来创建映像时, Docker 会检查. dockerignore 文件, 如果存在此文件, 它会逐行浏览文件并使用 Go 的 filepath.Match 规则以及 Docker 自身的一些规则来匹配文件名以此来进行忽略. 比如在. dockerignore 文件中包含 * .vs 将排除带有. vs 扩展名的文件. 我们可以使用以#开头的注释来解释在. dockerignore 中正在执行的操作. .dockerignore 可以帮助减小镜像大小, 文件越少意味着镜像越小, 镜像越快, 减少构建缓存失效, 如果日志或其他文件正在更改, 并且我们的镜像因其缓存而使其缓存失效, 则会降低构建周期. 综上我们针对需要使得我们所构建的镜像可以注意以下几方面:
1. 使用官方镜像, 可能很多文章或博客讲解的镜像已过时.
2. 若可能, 尽可能使用 Alpine 镜像, 以保持镜像轻量级.
3. 如果使用 apt, 在同一指令中将 RUN apt-get update 与 apt-get install 结合使用, 然后在该链式指令中链接多个包, 使用 \ 字符在多行中按字母顺序列出包, 最后使用 rm -rf /var/lib/apt/lists/* 的目的在于清除 apt 缓存而不会使其缓存保存到镜像层上. 例如: RUN apt-get update && apt-get install -y \package-one \package-two && rm -rf /var/lib/apt/lists/*
4. 将可能需要更改的指令尽量放在 Dockerfile 比较低的位置(可能的话)
5.. 使用. dockerignore 文件将不需要的和不必要的文件留在镜像之外.
6. 可以尝试结合使用 dive 库监控镜像层, 然后合理优化镜像大小.
.NET Core 使用 Docker 优化镜像大小
接下来我们来一起看看针对上一节所写的 Dockerfile 文件进行分析, 看看是否可以为镜像瘦身而进一步优化, 上一节的构建镜像文件说明书如下:
首先我们获取基础镜像, 然后只是复制项目文件而不是复制所有文件, 这可以避免额外无关的还原, 并允许我们重用中间镜像层, 如果我们更改项目文件, 只是会再次来一遍重新复制, 这也就意味着更快的构建! 如果是自包含的应用程序, 我们下载对应的镜像而不包含运行时镜像, 这样镜像大小最小, 同时最后运行时自包含应用程序则无需使用 dotnet 命令, 直接切换到项目根目录通过 CMD 执行即可.
移除未使用代码
我们使用预发布的包工具《》, 通过它我们可以查看应用程序并删除没有调用的代码和二进制文件, 接下来我们包括 Microsoft.Packaging.Tools.Trimming 添加包以及忽略文件基于上一节构建镜像进行如下改造.
- FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
- WORKDIR /App
- COPY *.csproj ./
- RUN dotnet restore
- COPY . ./
- RUN dotnet add package Microsoft.Packaging.Tools.Trimming -v 1.1.0-preview1-25818-01
- RUN dotnet publish -c Release -o out -r Linux-ARM /p:LinkDuringPublish=true
- FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS runtime
- WORKDIR /App
- COPY --from=build /App/out .
- ENV ASPNETCORE_URLS=http://+:8080
- ENTRYPOINT ["dotnet", "WebApi.dll"]
由如上第一张图我们可以看到, 当我们添加了忽略文件后, 它将上下文从 4.206MB 减少到 16.9KB, 而无需花费更多时间来发送上下文, 现在可以说是秒送.
总结
本节我们详细讲解了从哪几方面入手来瘦身镜像, 下一节我们深入讲讲 Docker 中的网络内容, 感谢您的阅读, 下节再会.
来源: https://www.cnblogs.com/CreateMyself/p/11407091.html