Docker构建优化解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Docker镜像用作Docker执行程序中的主映像。它们是容器的蓝图,提供了有关如何生成容器的说明。在本文中,我将介绍一些经常被忽视的概念,这些概念将有助于优化Docker镜像开发和构建过程。

     Docker镜像用作Docker执行程序中的主映像。它们是容器的蓝图,提供了有关如何生成容器的说明。在本文中,我将介绍一些经常被忽视的概念,这些概念将有助于优化Docker开发和构建过程。

      让我们从Docker构建过程的简短描述开始。这是通过使用Docker CLI工具运行docker build命令触发的过程。

       docker build命令根据Dockerfile的文件中指定的指令构建Docker。Dockerfile是一个文本文档,其中包含用户在命令行上调用以组装映像的所有有序命令。

       Docker由只读层组成。每层代表一个Dockerfile指令。这些层是堆叠在一起的,每个层都是上一层的变化的增量。通常可以认为这些层是缓存的一种形式。仅对更改的层进行更新,而不是对每个更改进行更新。

       下面的示例描述了Dockerfile的内容:


FROM registry.docker.com/baseimg/centos7-jdk8:latest
MAINTAINER Luga "luga_sx@outofmemory.cn";
RUN mkdir -p /tools/apps/{microserice}
RUN mkdir -p /tools/apps/{microserice}/cache
ADD {microserice}.jar /tools/apps/{microserice}/{microserice}.jar
EXPOSE 9999
ENV TZ 'Asia/Shanghai'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom -Djava.awt.headless=true -Denv=DEV -Dapollo.cluster=DEFAULT -Dspring.profiles.active=prm -Dfile.encoding=utf-8","-jar","/tools/apps/{microserice}/{microserice}.jar"]

       该文件中的每条指令代表Docker中的单独一层。以下是每条指令的简要说明:

       FROM:从JDK创建一个层Docker,(此处的镜像非Docker Hub上面直接拉取,而是基于源码自定义制作)

       COPY:从Docker客户端的当前目录添加文件

       RUN:使用make构建您的应用程序

       CMD:指定在容器中运行什么命令

       基于上述命令行,在构建过程中执行上述命令时,将在Docker中创建层,一个完整的Docker将由此诞生。然而,在实际的项目活动中,我们需要从性能、稳定性、安全性等等方面对我们所创建的Docker镜像进行不断的调整、优化,以满足业务场景需求。

       针对Docker的构建过程,我想分享一些优化建议,以帮助有效地构建镜像:      

临时容器

      Dockerfile定义的会生成短暂的容器。在这种情况下,临时容器是指可以停放并销毁,然后重建的容器,并使用绝对最小的设置和配置替换为新生成的容器。临时容器可以认为是一次性的。每个实例都是新的,并且与以前的容器实例无关。在开发Docker镜像时,我们应该利用尽可能多的临时模式。  

减少不必要的软件包

      尽量避免安装不必要的文件和软件包。Docker镜像应保持精简。这有助于提高可移植性,缩短构建时间,降低复杂性并减小文件大小。例如,在大多数情况下,不需要在容器上安装文本编辑器。不要安装任何非必需的应用程序或服务。    

实现.dockerignore文件

       .dockerignore文件排除与在其中声明的模式匹配的文件和目录。这有助于避免将不必要的大文件或敏感文件和目录发送到守护程序,并避免将它们添加到公共镜像。

       要在不重构源存储库的情况下排除与构建无关的文件,请使用.dockerignore文件。该文件支持类似于.gitignore文件的排除模式。    

排序多行参数

      尽可能通过字母数字排序多行参数来简化以后的更改。这有助于避免软件包重复,并使列表更易于更新。      

解耦应用

      依赖于其他应用程序的应用程序被视为“已耦合”。在某些情况下,它们托管在同一主机或计算节点上。这在非容器部署中很常见,但对于微服务,每个应用程序应存在于其自己的单独容器中。将应用程序解耦到多个容器中,可以更轻松地水平缩放和重用容器。例如,一个解耦的Web应用程序堆栈可能包含三个单独的容器,每个容器都有自己的唯一镜像:一个用于管理Web应用程序,一个用于管理数据库的容器以及一个用于内存中缓存的容器。将每个容器限制为一个进程是一个很好的经验法则。根据业务规则,使容器保持清洁和模块化。然后,如果容器相互依赖,则可以使用Docker容器网络来确保这些容器可以通信。    

最小化层数

      仅使用RUN、COPY和ADD等指令即可创建图层。其他指令仅仅是创建临时的中间镜像,并且最终不会增加构建的大小。在可能的情况下,我们可以在构建过程中包含其他工具或者调试信息,而无需增加最终镜像的大小。      

利用构建缓存

      在构建镜像时,Docker会逐步执行Dockerfile中的指令,并按顺序执行每个指令。在每条指令中,Docker都会在其缓存中搜索要使用的现有镜像,而不是创建新的重复镜像。

Docker镜像通常在构建的过程中遵循以下基本规则:

       1、从已在缓存中的父镜像开始,将下一条指令与从该基本镜像派生的所有子镜像进行比较,以查看是否其中一个是使用完全相同的指令构建的。如果不是,则高速缓存无效。在大多数情况下,仅将Dockerfile中的指令与子镜像之一进行比较就足够。

       2、对于ADD和COPY指令,将检查镜像中文件的内容,并为每个文件计算一个校验标识。在这些校验标识中通常不考虑文件的最后修改时间和最后访问时间。在缓存查找期间,将校验标识与现有镜像中的进行比较。如果文件中的任何内容(例如内容和元数据)发生了更改,则缓存将无效。

       3、除了ADD和COPY命令外,缓存检查不会查看容器中的文件来确定缓存是否匹配。例如,在处理RUN apt-get -y update命令时,不会检查容器中更新的文件以确定是否存在缓存命中。在这种情况下,命令字符串用于查找匹配项。

       4、缓存无效后,所有后续Dockerfile命令都会生成新镜像,并且不使用缓存。 

在CI管道中优化Docker镜像构建

      前面几节中提到的所有优化概念对于在CI管道中实施都是有效的。特别是缓存。如果Dockerfile发生了变化,那么利用缓存仍然是减少构建时间的最佳方法。作为CI管道的一部分,这是如何工作的?当使用Docker执行器作为构建作业的运行时,可以利用称为Docker层缓存(DLC)的功能来加快构建速度。

      当构建Docker镜像是CI流程的常规部分时,DLC是一项很不错的功能。DLC将保存在作业中创建的镜像层。DLC会缓存在工作期间构建的任何Docker镜像的各个层,然后在后续的CircleCI运行中重用未更改的镜像层,而不是每次都重新构建整个镜像。

      Dockerfile提交的次数越少,镜像构建步骤将运行得越快。DLC可以与机器执行程序和远程Docker环境(setup_remote_docker)一起使用。重要的是要注意,DLC仅在使用docker build,docker compose或类似的Docker命令创建自己的Docker镜像时有用,它不会减少所有构建启动初始环境所花费的时间。


相关文章
|
15天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
117 9
|
9天前
|
NoSQL Java Linux
《docker高级篇(大厂进阶):2.DockerFile解析》包括:是什么、DockerFile构建过程解析、DockerFile常用保留字指令、案例、小总结
《docker高级篇(大厂进阶):2.DockerFile解析》包括:是什么、DockerFile构建过程解析、DockerFile常用保留字指令、案例、小总结
158 75
|
30天前
|
机器学习/深度学习 人工智能 PyTorch
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
本文探讨了Transformer模型中变长输入序列的优化策略,旨在解决深度学习中常见的计算效率问题。文章首先介绍了批处理变长输入的技术挑战,特别是填充方法导致的资源浪费。随后,提出了多种优化技术,包括动态填充、PyTorch NestedTensors、FlashAttention2和XFormers的memory_efficient_attention。这些技术通过减少冗余计算、优化内存管理和改进计算模式,显著提升了模型的性能。实验结果显示,使用FlashAttention2和无填充策略的组合可以将步骤时间减少至323毫秒,相比未优化版本提升了约2.5倍。
47 3
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
|
27天前
|
前端开发 UED
React 文本区域组件 Textarea:深入解析与优化
本文介绍了 React 中 Textarea 组件的基础用法、常见问题及优化方法,包括状态绑定、初始值设置、样式自定义、性能优化和跨浏览器兼容性处理,并提供了代码案例。
52 8
|
1月前
|
数据库 Docker 容器
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。Dockerfile定义了构建镜像所需的所有指令,包括基础镜像选择、软件安装、文件复制等,极大提高了开发和部署的灵活性与一致性。掌握Dockerfile的编写,对于提升软件开发效率和环境管理具有重要意义。
58 9
|
30天前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
23天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
180 77
|
5天前
|
搜索推荐 安全 数据安全/隐私保护
7 个最能提高生产力的 Docker 容器
7 个最能提高生产力的 Docker 容器
73 35
|
1月前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
|
4天前
|
Ubuntu Linux 开发工具
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈
Docker 是一个开源的容器化平台,允许开发者将应用程序及其依赖项打包成标准化单元(容器),确保在任何支持 Docker 的操作系统上一致运行。容器共享主机内核,提供轻量级、高效的执行环境。本文介绍如何在 Ubuntu 上安装 Docker,并通过简单步骤验证安装成功。后续文章将探讨使用 Docker 部署开源项目。优雅草央千澈 源、安装 Docker 包、验证安装 - 适用场景:开发、测试、生产环境 通过以上步骤,您可以在 Ubuntu 系统上成功安装并运行 Docker,为后续的应用部署打下基础。
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈