Docker构建镜像的三大优化方法指南

 更新时间:2025年11月26日 09:18:14   作者:敲上瘾  
这篇文章主要为大家详细介绍了Docker构建镜像的三大优化方法,包括CMD/ENTRYPOINT、多阶段构建与缓存优化,下面就跟随小编一起深入了解下吧

一、cmd与entrypoint

基本概念:

CMD指令: 指定容器启动时默认执行的命令。它不会在构建时执行,只是在镜像中记录了"当有人运行这个容器时,默认应该执行什么"。

ENTRYPOINT指令: 类似CMD默认执行一个指令,但它是将配置容器作为一个可执行程序来运行。它让容器表现得像一个独立的二进制文件。

特性:

共同特性:

  • 覆盖特性: 如果在Dockerfile中写了很多个这样的指令,那么后一个的会覆盖前面的。

区别:

  • cmd:docker run时指定命令会把cmd命令覆盖。
  • entrypoint:docker run 时添加的指令,会默认作为 ENTRYPOINT 的参数;若需覆盖 ENTRYPOINT,需通过 --entrypoint 参数指定

指令的两种格式:

  • exec模式:把命令放在Json数组
  • shell模式:直接把命令放在后面
  • 效果上的差异:
    • exec模式:指令程序被直接启动,pid为1,可直接与程序进行交互。
    • shell模式:不是直接启动指令程序,pid不是1,而是作为sh的子程序运行。需要通过sh与程序进行交互。

示例:

CMD nginx -g "daemon off"(shell模式)

执行:/bin/sh -c "nginx -g "daemon off"

CMD ["nginx","-g","daemon off"](exec模式)

执行:nginx -g "daemon off"

使用推荐:

使用exec模式编辑,CMDENTRYPOINT配合使用:entrypoint负责可执行程序,cmd负责参数传入。

覆盖测试

  • 创建Dockerfile
  • 填写多条CMD语句
  • 创建镜像
  • 启动容器
  • Dockerfile文件中CMD改为ENTRYPOINT

Dockerfile文件:

FROM busybox
CMD echo "hello world"
CMD echo "hello docker"

构建镜像:docker build -t cmd:v0.1 .

运行镜像:

CMD测试:

ENTRYPOINT测试:

可使用–entrypoint选项指定指令执行:

shell与exec

exec模式:

shell模式:

cmd与entrypoint组合

二、优雅构建镜像(过滤文件)

很多时候我们会将当前目录(构建上下文)中的所有文件拷贝给docker容器。但很多时候,我们的项目中包含一些不需要被打进镜像的文件,这些文件不仅会增加镜像大小,延长构建时间,还可能带来安全风险。这时候.dockerignore就该上场了。

什么是 .dockerignore

.dockerignore 文件是 Docker 构建过程中的一个重要工具,它的作用类似于 .gitignore,用于指定在构建 Docker 镜像时应该忽略哪些文件和目录,防止它们被复制到镜像中。

为什么要使用 .dockerignore

主要好处:

  • 减小镜像大小 - 避免将不必要的文件打包进镜像
  • 提高构建速度 - 减少 COPYADD 指令处理的数据量
  • 增强安全性 - 防止敏感文件(如密钥、配置文件)意外进入镜像
  • 避免缓存失效 - 不重要的文件变化不会导致构建缓存失效

如何使用 .dockerignore

基本语法:

  • * 匹配任意数量字符
  • ? 匹配单个字符
  • ** 匹配任意层级的目录
  • ! 表示例外(不忽略)

示例:

# * - 匹配任意数量字符(除了路径分隔符)
*.log          # 忽略所有 .log 文件
src/*.js       # 忽略 src 目录下的所有 .js 文件
#-------------------------------------------------------
# ? - 匹配单个字符
file?.txt      # 忽略 file1.txt, file2.txt 等
#-------------------------------------------------------
# ** - 匹配任意层级的目录
**/test        # 忽略所有 test 目录
src/**/*.js    # 忽略 src 下任意层级的 .js 文件
#-------------------------------------------------------
# ! 表示例外(不忽略)
!README.md 	#保留README.md 文件
*.md 			#忽略其他 .md 文件
#-------------------------------------------------------

文件位置:.dockerignore 应该放在 Dockerfile 同一目录下。

实战示例:

三、多阶段构建

Docker 多阶段构建允许你在一个 Dockerfile 中定义多个“构建阶段”(图中的 Stage1, Stage2, …),每个阶段都是一个独立的镜像构建过程,并且你可以有选择地将前一个阶段的产物复制到后一个阶段,最终只产出最后一个阶段的镜像。

这解决了传统单阶段构建模式(图中的“单阶段”)所带来的问题。

1.单阶段构建

  • 模式:在一个 Docker 镜像中完成所有事情(编译、测试、打包、运行)。
  • 问题层次多,体积大、部署时间长、安全性差。

2.手动拆分

  • 模式:开发人员意识到单阶段的问题,于是手动拆分流程。
  • 问题流程复杂、不标准。

3.多阶段构建

模式:用一个 Dockerfile 定义多个阶段,自动完成“按需构建和复制”。

如何工作

  • stage1(编译阶段):使用一个包含 java/mavengcc 的较大镜像,任务是将源代码编译成可执行的二进制文件(如 JAR 包或可执行文件)。这个阶段可以包含多个步骤,比如用 junit 进行测试。
  • stage2(运行阶段):使用一个非常精简的镜像(比如只包含 java 运行时或 glibc)。然后,使用 COPY --from 指令,只从 stage1 里把编译好的最终产物(JAR 包)复制过来。
  • 最终镜像:只包含 stage2 的内容,也就是一个最精简的运行环境和你的应用程序。stage1 中的所有构建工具(Maven, GCC)都被抛弃了,不会出现在最终镜像里。

4.测试

测试文件:

#include <stdio.h>
int main()
{
		printf("hello docker");
		return 0;
}

单阶段构建:

FROM ubuntu:22.04

# 设置国内源(阿里云Ubuntu镜像)
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
    sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list

# 更新软件包列表并安装gcc
RUN apt-get update && \
    apt-get install -y gcc && \
    gcc -v

# 设置工作目录
WORKDIR /src

# 拷贝源文件
COPY demo.c .

# 编译源文件并清理
RUN gcc demo.c -o demo && \
    rm -f demo.c && \
    apt-get remove -y gcc && \
    apt-get autoremove -y && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 运行可执行文件
CMD ["/src/demo"]

多阶构建:

FROM ubuntu:22.04 as buildstage

# 设置国内源(阿里云Ubuntu镜像)
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
    sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list

# 更新软件包列表并安装gcc
RUN apt-get update && \
    apt-get install -y gcc && \
    gcc -v

# 设置工作目录
WORKDIR /src

# 拷贝源文件
COPY demo.c .

# 编译源文件并清理
RUN gcc demo.c -o demo && \
    rm -f demo.c && \
    apt-get remove -y gcc && \
    apt-get autoremove -y && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
    
FROM busybox
COPY --from=buildstage /src/demo /src/
CMD ["/src/demo"]

四、合理使用缓存

Docker 层缓存原理

Docker 镜像由只读层组成,每一层对应 Dockerfile 里的一条指令(RUNCOPYADD 等)。构建时:从第一条指令开始,Docker 检查是否已有缓存层(基于指令字符串和文件内容);如果缓存存在,就复用该层,继续下一条;一旦某条指令的缓存没命中(指令内容变化,或 COPY/ADD 的文件内容变化),后续所有指令都会重新执行,不再使用缓存。

所以为了提高构建效率,通常会把变更频繁的指令或文件放在后面执行。示例:代码常常会被频繁修改,所以我们把它放在后面执行,把编译软件的安装放在前面就能提高二次构建的效率。

注意:两种方式初次构建的时间是一样的,主要影响的是二次构建。

测试方式:

  • copy在前run安装在后,完成初次构建
  • 更改源代码,然后再进行二次构建并记录时间
  • run安装前copy放在后,完成初次构建
  • 更改源代码,然后再进行二次构建并记录时间
  • 对比两次构建的时间

以上就是Docker构建镜像的三大优化方法指南的详细内容,更多关于Docker镜像构建的资料请关注脚本之家其它相关文章!

相关文章

  • MongoDB Docker 镜像制作与部署完整流程

    MongoDB Docker 镜像制作与部署完整流程

    该文章介绍了如何使用Docker部署MongoDB,包括创建Dockerfile、配置文件、数据库初始化脚本,构建镜像、创建和运行容器、镜像导出与导入、扩展功能、安全建议和故障排除,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • Docker学习之基于Dockerfile搭建JAVA Tomcat运行环境的方法

    Docker学习之基于Dockerfile搭建JAVA Tomcat运行环境的方法

    本篇文章主要介绍了Docker学习之基于Dockerfile搭建JAVA Tomcat运行环境的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-02-02
  • 如何在 Ubuntu 下通过 Docker 部署 Caddy 服务器

    如何在 Ubuntu 下通过 Docker 部署 Caddy 

    本文介绍了如何在Ubuntu系统下通过Docker部署Caddy服务器,首先安装Docker,然后启动Docker服务并设置为开机自启,接着拉取Caddy镜像,并创建一个Caddyfile配置文件,使用命令运行Caddy容器,并将本地的Caddyfile挂载到容器内,感兴趣的朋友跟随小编一起看看吧
    2025-03-03
  • SpringCloud基于Docker和Docker-Compose的项目部署过程

    SpringCloud基于Docker和Docker-Compose的项目部署过程

    本文介绍了如何卸载旧版本Docker、更新系统、安装Docker及其依赖,并设置国内镜像源以加快下载速度,详细说明了如何安装Docker Compose、配置镜像加速器,并展示了如何使用Docker Compose部署SpringCloud项目,提供了更新和重启容器的方法
    2024-10-10
  • Docker下利用jenkins和docker实现持续交付

    Docker下利用jenkins和docker实现持续交付

    这篇文章主要介绍了利用jenkins和docker实现持续交付功能,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • 不重启docker进程,重新reload加载配置过程

    不重启docker进程,重新reload加载配置过程

    这篇文章主要介绍了不重启docker进程,重新reload加载配置过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-09-09
  • Docker容器之间数据传输的实现

    Docker容器之间数据传输的实现

    本文主要介绍了Docker容器之间数据传输的实现,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Centos8.3、docker部署springboot项目实战案例分析

    Centos8.3、docker部署springboot项目实战案例分析

    这篇文章主要介绍了Centos8.3、docker部署springboot项目实战记录,包括docker安装,开启docker远程访问端口的方法及配置idea docker环境的方法,需要的朋友可以参考下
    2021-06-06
  • docker保存镜像到本地并加载本地镜像文件详解

    docker保存镜像到本地并加载本地镜像文件详解

    平常我们下载docker镜像会通过配置国内源来加速下载,但是有时候会有另外的需求,比如某个机器不能联网,我们就需要从其他机器下载,打包后,拷贝到这个机器,下面这篇文章主要给大家介绍了关于docker保存镜像到本地并加载本地镜像文件的相关资料,需要的朋友可以参考下
    2022-08-08
  • 如何清理docker产生的垃圾文件

    如何清理docker产生的垃圾文件

    这篇文章主要介绍了如何清理docker产生的垃圾文件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07

最新评论