Dockerfile 全景指南:从入门编写dockerfile到生产环境镜像优化实战,一步步带你从啃透制作指令到镜像制作落地!

文章目录

本篇摘要

本文系统解析 Dockerfile 全指令集与实战技巧,涵盖镜像构建原理、多阶段优化、缓存机制及安全实践。通过快照与 Dockerfile 对比,详解如何高效封装应用、缩减镜像体积,并提供企业级镜像优化方案,助力构建生产就绪的容器化应用。

一.镜像制作的原因

  1. 代码封装发布:为了将自主编写的应用程序代码直接打包到镜像中,实现与镜像一体化的发布和部署。

  2. 安全合规要求:为避免第三方镜像可能存在的安全漏洞或未知风险,确保运行环境的安全与可控。

  3. 功能定制扩展官方镜像无法满足特定需求(如为数据库添加审计等额外功能),需要通过自定义镜像来实现。

  4. 内部规范统一:遵守公司内部规定,需使用自有的操作系统或基础环境作为基准来构建镜像,以符合统一的标准和管理流程。

二.Docker镜像制作的两种方式

  1. 制作快照(适用于偶尔制作的镜像)
  • 方法:先启动一个基础容器(如 Ubuntu),进入容器内部手动安装和配置所有所需软件,最后将该容器的整个状态打包成一个新镜像。
  • 类比:类似于给当前系统拍一张"快照"或"备份"。
  1. Dockerfile构建(适用于经常更新的镜像)
  • 方法 :将所有安装和配置步骤编写到一个名为 Dockerfile 的文本文件中,然后使用 docker build 命令自动构建镜像。
  • 优势:过程透明、可重复,易于版本管理和自动化,是推荐的标准做法。

三.基于快照模式制作C++ hello world 镜像

制作流程

基于centos:7原镜像进行把对应的容器启动然后在容器中进行对应操作,接着把它commit成镜像,下次启动就直接一次性启动执行对应命令,这样一个简单的镜像就制作好了。

首先对应宿主机进行文件编写:

启动对应centos:7容器并以bash交互进去:

把宿主机对应的test文件拷贝过去:

下面在对应的容器中进行centos 镜像源安装:

下面安装完gcc开始运行:

接着把它commit成对应的镜像;

下面进行一次性执行容器命令:

  • 执行完后也是立刻退出了。
  • 可以看到对应的commit的过程保留文件系统+底层元数据,而之前的export就不会。

基于快照模式的提交镜像总结

  • 可以发现当进行commit进行制作的时候,当使用方完全看不到对应的制作过程;而且如果想要修改的话,又要重头再制作(不知道这个镜像到了哪一步);而上面操作,其实运行容器的时候没有用到gcc;倒不如直接把对应的exe拷贝进容器中,因此看起来是比较臃肿的。

  • 而后面要介绍的Dockerfile就完美的解决了这一点。

四.dockerfile镜像制作

dockerfile概念

  • Dockerfile 是一个文本脚本文件,用于自动化和定义 Docker 镜像的构建过程。

  • 镜像的定制就是定制每一层的配置和文件。Dockerfile 中的每一条指令 都会对应构建出镜像的一个层级

  • 通过在其中写入一系列的命令(例如复制文件、安装软件、配置环境等),来描述每一层应当如何被构建。

  • 通过执行这个脚本(使用 docker build 命令),可以自动地构建出一个符合用户定制需求的、新的 Docker 镜像。

  • Dockerfile 中最后一个 FROM指令决定了最终镜像的根基,之前的阶段只是为它服务的临时环境。​

如图:

总而言之,Dockerfile 是将手动构建镜像的步骤记录到一个自动化脚本中,从而实现镜像构建的流程化、可重复和可管理。

为什么需要 Dockerfile

  • 官方镜像通常无法直接满足应用需求,需要将自己开发的代码打包进去,制作成符合要求的自定义应用镜像(基于commit的快照模式改造)。

  • 相比手动执行命令并提交(docker commit)的不可追溯和易遗漏,Dockerfile 能将构建过程自动化,确保每次构建的结果一致。

  • 使用 docker commit 制作的是"黑箱镜像",构建步骤不透明。而 Dockerfile 是明文脚本,所有操作清晰可见,易于理解和二次开发。

  • docker commit 容易将运行时产生的临时文件和未清理的依赖打包进镜像,导致镜像臃肿。Dockerfile 可以通过多阶段构建等功能,分离编译和运行环境,产出更标准、体积更小的镜像。

制作好对应的镜像然后放到对应仓库,后面就可以直接同步push下对应镜像然后实例化出对应的容器,在不同的环境进行部署测试等:

dockerfile常见的指令

对应参考docker官方文档

1.FROM指令

  1. 功能FROM 指令用于指定构建镜像所依赖的基础镜像,后续所有指令均在此基础镜像提供的环境中执行。

  2. 位置要求 :必须是 Dockerfile 中首个非注释指令,或紧跟在 ARG 指令之后。

  3. 镜像拉取:若本地不存在指定镜像,Docker 会尝试从公共仓库自动拉取;若镜像不存在则报错。

  4. 多阶段构建 :可通过多次使用 FROM 指令创建多个镜像,或将某一构建阶段作为另一阶段的依赖(需配合 AS <name> 命名)。

  5. 标签默认值 :若未指定镜像标签(<tag>),默认使用 latest 标签。

  6. 语法参数

  • --platform:指定目标平台架构(如 linux/amd64)。
  • <image>:基础镜像名称(如果是scratch的话就是从空镜像开始制作;做出来就是基础镜像)。
  • <tag>/<digest>:使用标签或哈希值精确指定镜像版本。
  • AS <name>:为构建阶段命名,便于多阶段构建中引用。

演示下:

在对应目录创建dockerfile文件:

基于基本镜像centos:7来构建新镜像:

  • 进行构建然后这里提示说,建议在build的时候进行--platform指定(. 是当前目录作为dockefile上下文)。
  • 创建成功(说白了就是搞了个centos:7的副本)。
  • 启动这个镜像来实例化容器执行一次性命令。

2.MAINTAINER指令

  • 已废弃的 Docker 指令
  • 原用途:标注镜像作者信息
  • 现建议:改用 LABEL maintainer="作者名"
  • 语法示例:MAINTAINER 姓名<邮箱>

(注:现使用仅触发警告,不影响构建)

演示下:

  • 这里提示已经废弃掉了。
  • 成功启动,可以运行,看到对应的author内容发生改变。

3.LABEL指令

  1. 功能:用于为 Docker 镜像添加元数据(描述信息)。
  2. 格式:元数据以键值对(key=value)形式存储。
  3. 语法LABEL <键>=<值> <键>=<值> ...(可同时定义多个标签)。
  4. 用途:记录作者、版本、描述等镜像信息,方便管理。

演示下:

  • 可以看到成功运行。
  • 查看镜像详情,可以看到对应的labels被添加了。

4.COPY指令

  1. 功能:将主机上的文件或目录复制到镜像内部。
  2. 语法COPY [参数] <源路径> <目标路径>
  3. 参数
  • --chown:可设置复制后文件的所属用户和组。
  • --from:可从多阶段构建的前一阶段复制文件。
  1. 规则
  • 源路径必须在构建上下文内。
  • 复制目录时会递归复制其内容(不包括目录本身)。
  • 复制多个文件或使用通配符时,目标路径必须是目录(以/结尾)。
  • 目标路径不存在时会自动创建。

演示下:

首先编写对应dockerfile:

查看对应的组别有哪些(随便启动一个对应的NGINX容器):

  • 这里可以根据第一个作为不同的组进行chown操作。

下面编写对应指令:

  • 在宿主机制作对应文件。
  • 对应镜像制作成功,然后去对应的容器的bash下查看。
  • 对应的拥有者与从属组更改完成,对应的文件内容也发生拷贝覆盖。

5.ENV指令

  1. 作用 :在镜像里设置环境变量(就像设置全局配置)。
  2. 使用 :设置后,后面的指令(如 RUN, COPY)都能用 $变量名使用这个值。
  3. 写法ENV 变量名=值(例如:ENV APP_HOME=/app)。

演示下:

编写dockerfile:

  • 成功打成镜像。

下面进入对应容器看下:

  • 也是成功显示。

6.WORKDIR指令

  1. 核心功能 :用来设置工作目录 ,相当于 cd 命令。之后的所有指令(如 RUN, CMD, COPY, ADD)都会在这个目录下执行(指定目录不存在就会创建)。

  2. 基本语法WORKDIR /路径/到/目录。路径可以是绝对路径(如 /app),也可以是相对路径。

  3. 默认目录 :如果不设置,默认的工作目录是容器文件系统的根目录(/)。

  4. 相对路径 :如果使用相对路径(如 subdir),它会基于前一条 WORKDIR 指令设置的路径。

  5. 支持变量 :路径里可以使用之前通过 ENV 指令定义的环境变量(如 WORKDIR $APP_HOME)。

演示下:

  • 镜像成功构建成功(为啥有悬空镜像? 重复构建同名镜像时,Docker会将旧镜像的标签转移给新镜像,导致旧镜像变成无标签的状态。)。
  • 发现对应的工作目录确实变了,也就是进入对应的bash就回来到对应工作目录(也就是没有指定对应目录默认都会在这个目录操作)。

7.ADD指令

  1. 核心功能 :用于复制文件,比 COPY 功能更强,支持自动解压压缩包(如 .tar)和从 URL 下载文件(但是url下载后不会自动解压)

  2. 基本语法

    ADD [--chown=<用户>:<组>] <源路径>... <目标路径>

    路径包含空格时,可以用引号格式。

  3. 关键参数 --chown :在复制时可同时修改文件的所有者和所属组 (如 --chown=user:group)。

  4. 路径说明

  • <源路径>:支持使用通配符。
  • <目标路径> :必须是容器内的路径,建议使用绝对路径 ,否则会相对于 WORKDIR 指令设置的目录。

演示下:

对应的nginx下载的官网:

下面测试下直接url抓过来以及直接tar包拿进来效果:

首先把对应tar.gz对应的压缩包到当前目录方便cp;对于wget直接从网站爬就行:

下面进行镜像构建:

  • 发现了对应的url的话只cp对应压缩包进来不进行解压;而对应的压缩包cp的话自动解压;还发现对于当前目录操作,默认当成了对应的工作目录来进行。

8.RUN指令

  1. 核心功能 :在 docker build 构建镜像的过程中执行命令(例如安装软件、编译代码等)。

  2. 两种语法形式

  • Shell 形式RUN <command>

默认在 /bin/sh -c 下执行命令;支持 Shell 特性,如变量替换、通配符(*)等。

  • Exec 形式RUN ["executable", "param1", "param2"]

直接执行程序,不通过 Shell;避免 Shell 解析的歧义,格式更清晰;不支持 Shell 特性,如需使用必须显式调用 Shell(如 RUN ["/bin/bash", "-c", "your command"])。

  1. 使用场景:通常用于安装依赖包、下载编译代码、执行构建脚本等任何需要在构建阶段准备镜像环境的操作。

演示下:

先演示下简单使用:

  • 把对应的从网站wget下来的压缩包解压到对应目录(这里用的包含shell的语法)。
  • 发现成功解压。

下面测试基于ubuntu 解压安转nginx:

  • 对应exec显示显示shell调用成功,对应的nginx安装完成。
  • 对应html首页也被覆盖。

9.CMD指令

  1. 核心功能 :在容器启动时执行命令,为容器提供默认的运行程序。
  2. 与 RUN 的区别RUN镜像构建时 执行,用于安装配置;CMD容器运行时 执行,用于启动应用(相当于main函数)。
  3. 语法形式
    • 推荐格式CMD ["executable", "param1", "param2"]
    • 为 ENTRYPOINT 提供参数CMD ["param1", "param2"]
    • Shell 格式CMD command param1 param2
  4. 重要特性
    • 一个 Dockerfile 中可以有多个 CMD,但只有最后一个会生效
    • 在启动容器时,docker run 后面跟的命令可以覆盖 Dockerfile 中的 CMD 指令。
    • 与entrypoint都出现的时候,结合起效果。
  5. 注意事项 :使用 JSON 数组格式(Exec form)时,必须使用双引号

演示下:

  • 基于之前的ubuntu镜像进行让实例化的容器的主进程就去执行启动nginx的前台任务。
  • 这里发现对应的cmd变了;也就是容器一启动里面的主进程就去执行这个指令了;而访问对应8090端口就被映射到容器的80端口(nginx就默认部署在80端口上),因此看到对应效果。
  • 如果没有更改镜像的cmd默认就是bash;自然一启动没收到一次性命令就退出来了。

10.EXPOSE指令

  1. 作用 :只声明容器会用的端口,不自动打开端口。
  2. 本质 :是给用户的说明文档,告诉别人这个镜像里的服务用了哪些端口。
  3. 用法EXPOSE <端口号>EXPOSE <端口号>/<协议>(如 EXPOSE 80/tcp)。
  4. 关键 :运行容器时必须加 -p(如 -p 80:80才能从外部访问

演示下:

  • 只是声明说是有这个端口,并没有完成映射。
  • curl一下发现curl宿主机80端口没有被转发到对应容器80端口,故只是声明。

11.ENTRYPOINT指令

  1. 核心功能 :指定容器启动时的主入口命令,让容器像独立应用程序一样运行。

  2. 两种语法形式

    • Exec 形式(推荐)ENTRYPOINT ["可执行命令", "参数1", "参数2"]
    • Shell 形式ENTRYPOINT 命令 参数1 参数2
  3. 关键注意事项 :使用 Exec 形式(JSON数组)时,必须使用双引号,使用单引号会导致错误。

  4. 与 CMD 的区别ENTRYPOINT 定义的命令通常不会被 docker run 的命令覆盖,而 CMD 提供的默认参数可以被覆盖。两者常结合使用。

演示下:

基于之前的ubuntu的dockerfile对于cmd配合entrypoint结合使用:

  • build后启动,发现直接就是前台运行不是bash(直接退出);说明两者结合使用变成主进程的命令了。
  • 查看容器详情可以发现。
  • 可以发现这里如果是entrypoint或者两者结合使用的话,后面的命令就不能覆盖掉之前的命令给主进程(这里是把后面的当成参数传给entrypoint了,然后不认识这些参数故报错)。

如果是cmd模式呢?

  • 这里可以看到成功打印出来了,此时就是把对应的参数给cmd了,也就是覆盖cmd原先dockerfile中设置的了,直接主进程就执行新的命令了。
  • 这里如果使用的是entrypoint;那么--entrypoint :命令 -c:参数才能发生指令覆盖;而cmd本身就会发生覆盖。

总结下:

entrypoint可以结合cmd(做entrypoint参数使用);然后如果是单entrypoint或者结合使用的,那么此时run后面命令就是给entrypoint做参数(可能无法识别);但是如果是cmd状态,run的时候添加参数就是覆盖cmd让主进程执行。

12.ARG 指令

  1. 作用 :定义构建时可修改 的变量,类似ENV但仅在docker build阶段有效。
  2. 语法ARG <变量名>[=默认值](默认值可选)。
  3. 传参 :通过docker build --build-arg <变量名>=<值>覆盖默认值。
  4. 作用域:从定义处开始生效,定义前无法使用(即使传参也无效)。
  5. 优先级 :若ENVARG同名,ENV的值会覆盖ARG的值;也就是只存在于对应dockerfile中不进镜像。
  6. 用途:灵活控制软件版本、路径等构建参数,提升Dockerfile可复用性。

演示下:

  • 相当于别名(只在对应的dockerfile文件有效)。
  • 就是对应版本ubuntu。

但是如果不想改dockerfile但是想换个版本;此时就可以在build的时候借助--build-arg 来修改对应的VERSION:

  • 这里查看对应镜像版本就是更新后的22.10.

总结下:

如果只希望在dockerfile中起效,因此可以使用arg指令;比如对应的还有需要动态构建(如镜像版本升级等);此时arg就能发挥作用。

13.VOLUME指令

用法:

  • VOLUME <挂载点路径>(直接指定)
  • VOLUME "\<挂载点路径\>"(JSON数组格式)
  1. 作用 :在容器里自动创建备份盘(匿名数据卷),防止数据丢失。
  2. 特点
    • 备份盘位置由 Docker 自动分配(用户不能指定主机目录)。
    • 即使启动命令忘了用 -v,数据也会存下来。
    • 容器删除后,备份盘里的数据还在
  3. 优先级 :如果用户启动时用了 -v 指定目录,则以 -v 为准,这个"自动备份盘"就不生效了。
  4. 典型用途:像 MySQL 这类有重要数据的容器,必须用它确保数据安全。

下面来演示下:

  • 这路不输入-v也就是默认匿名卷存储在对应的/var/lib/docker/volumes下。
  • 确实符合预期,并且挂载也是volume。

如果加上-v也就是覆盖默认的volume,以-v为主:

  • 把对应宿主机当前目录的文件同步过去了。
  • 此时挂载方式也改变了。

14.SHELL指令

  1. 核心功能 :用于覆盖 Docker 容器中执行命令时使用的默认 Shell 程序

  2. 默认 Shell

    • Linux 系统 :默认是 ["/bin/sh", "-c"]
    • Windows 系统 :默认是 ["cmd", "/S", "/C"]
  3. 基本语法 :必须以 JSON 数组格式编写。

    SHELL ["可执行文件", "参数"]

    • 例如:SHELL ["/bin/bash", "-c"]
  4. 重要特性

    • 可以在 Dockerfile 中多次使用
    • 每条 SHELL 指令都会覆盖 之前的所有 SHELL 指令,并影响其后的所有指令。
  5. 主要用途 :此指令在 Windows 容器 中特别有用,因为 Windows 上有两种常用的 Shell:CMDPowerShell,可以通过该指令进行切换和指定。

演示下:

  • 这里从ubuntu默认的sh切换成bash;来详细展示过程。
  • 这里可以通过打印出执行过程看出不一样证明构建过程中shell变化了sh-->bash。

15.USER指令

  1. 功能 :用于设置容器运行时或执行后续指令(如 RUN, CMD)的默认用户身份,不再默认使用 root 用户,以提升安全性。
  2. 语法 :支持两种格式
    • 用户名/组名:USER <user>[:<group>]
    • 用户ID/组ID:USER <UID>[:<GID>]
  3. 参数
    • user / UID:指定用户名或用户 ID
    • group / GID:(可选)指定用户组名或组 ID
  4. 注意事项 :指定的 UID 必须是容器内 /etc/passwd 文件中存在的有效用户 ID,否则运行会失败。

演示下:

  • 这里默认是root用户及用户组,然后把它设置成nginx进行文件操作;然后改回root继续创建mysql再进行文件操作。

下面build后进行查看对应容器目录:

  • 发现用户及用户组确实变了。

16.healthcheck指令

  1. 核心功能 :用于检查容器内应用服务的健康状态,能检测进程虽在运行但服务已不可用(如死循环、服务僵死)的情况。

  2. 两种语法形式

    • HEALTHCHECK [OPTIONS] CMD command:在容器内运行指定命令来检查健康状况。
    • HEALTHCHECK NONE禁用从基础镜像继承的任何健康检查。
  3. 关键参数(OPTIONS)

    • --interval=DURATION:检查间隔时间(默认 30秒)。
    • --timeout=DURATION:等待命令响应的超时时间(默认 30秒)。
    • --retries=N:连续失败多少次才判定为不健康(默认 3次)。
    • --start-period=DURATION:容器启动后,等待多久开始第一次检查(默认 0秒)。
  4. 返回值含义(可以通过对应日志详细观看)

    • 0:成功,容器健康。
    • 1:失败,容器不健康。
    • 2:保留值,不使用。
  5. 主要目的 :让 Docker 引擎能更智能地监控容器内应用的实际状态,而不仅仅是进程是否存在(注意健康(自定义)和运行不是一个状态)。

演示下:

下面启动对应容器进行curl自己演示下health:

  • 正常执行完命令就说明健康。
  • docker ps可以看到从开始检测到健康状态。

下面检测下让它出现不健康:

  • 这使用bash覆盖掉nginx默认的启动命令(启动web);故此时只是一个shell啥也不干。
  • ps查看到到时间就失败。

17.ONBUILD指令

也就是延迟触发器!

  1. 作用:现在不执行,等别人拿我这个镜像当基础去构建时,再自动执行我定义的指令。
  2. 写法ONBUILD <Dockerfile指令>,例如:ONBUILD ADD . /app/src
  3. 用途 :专门用来做可复用的基础镜像,自动帮后续的"子镜像"完成一些通用操作。

演示下:

  • 第一次发现对应下面没有对应文件。

然后复用下上面的镜像:

  • 发现延迟成功。

18.STOPSIGNAL指令

  1. 核心功能 :用于设置容器停止时,Docker 引擎发送给容器内主进程的系统信号 ,以控制容器的停止方式(根据dockerfile里设置的来覆盖掉本身stop(优雅退出)时候的信号)。

  2. 基本语法STOPSIGNAL <信号>

    • 信号可以是数字代号(如 9)。
    • 也可以是信号名称(如 SIGKILL)。
  3. 常见信号

    • SIGTERM (15)默认信号。礼貌地请求进程终止,允许其完成清理工作。
    • SIGKILL (9):强制立即终止进程,不给进程任何清理的机会。
    • SIGHUP (1):通常用于通知进程重新加载配置。
    • SIGINT (2) :模拟键盘 Ctrl+C 的中断操作。
    • SIGSTOP (19):暂停进程的执行。
  4. 主要用途:通过发送不同的信号,可以更优雅、更可控地停止容器中的应用,例如让应用有时间保存状态、完成正在处理的请求后再退出。

演示下:

  • nginx前台占用宿主机shell启动。

  • stop时候发送对应信号这里显示不是优雅退出,收到的是9好信号。

下面启动个没被覆盖stop信号的普通nginx镜像:

  • 这里可以看到优雅的退出。

指令总览:

常见指令清单:

指令 功能描述 备注
FROM 构建镜像基于哪个镜像(基础镜像) 必须掌握
MAINTAINER 镜像维护者姓名或邮箱地址 已废弃,被 LABEL 替代
LABEL 为镜像添加元数据(如版本、描述等信息) 必须掌握
COPY 拷贝文件或目录到镜像中,不支持自动下载或解压 必须掌握
ADD 拷贝文件或目录到镜像中,支持 URL 自动下载和压缩包自动解压 必须掌握
WORKDIR 设置镜像内的工作目录(后续命令均在此目录下执行) 必须掌握
RUN 在构建过程中执行命令(如安装软件、配置环境等) 必须掌握
VOLUME 声明容器中的挂载点(数据卷) 必须掌握
EXPOSE 声明容器运行时监听的端口(仅声明,实际映射需在运行时指定) 必须掌握
ENV 设置环境变量(供后续指令或容器运行时使用) 必须掌握
CMD 指定容器启动时默认执行的命令(可被运行时覆盖) 必须掌握
ENTRYPOINT 指定容器启动时的程序入口(与 CMD 协同或独立使用) 必须掌握
ARG 定义构建时可传递的参数(仅在构建阶段有效) 使用较少
SHELL 指定 RUN、CMD、ENTRYPOINT 使用的默认 shell 使用较少
USER 指定运行容器时的用户名或 UID 必须掌握
HEALTHCHECK 定义容器健康检查方式(如检测服务是否就绪) 必须掌握
ONBUILD 定义延迟执行的指令(仅在以当前镜像为基础镜像构建下一级镜像时触发) 使用较少
STOPSIGNAL 覆盖容器停止时发送的系统信号 使用较少

dockerfile之build介绍

  1. 功能 :用于根据 Dockerfile 文件和构建上下文(代码、资源等)创建出一个新的 Docker 镜像

  2. 语法docker build [OPTIONS] PATH | URL | -

  3. 常用关键参数

    • -t / --tag为生成的镜像命名和打标签 (格式:name:tag),这是最常用的参数。
    • -f:指定使用的 Dockerfile 的路径(如果文件名不是默认的 Dockerfile 或不在上下文根目录时使用)。
    • --no-cache禁用缓存,从头开始构建,确保获取最新依赖。
    • --build-arg:设置构建时的变量,可传入 Dockerfile 中的 ARG 指令。
    • -q / --quiet:安静模式,成功构建后只输出最终的镜像 ID,不显示冗长的构建过程。
    • --network:设置构建过程中 RUN 指令的网络模式。
    • --label=[] :设置镜像使用的元数据。
  4. 构建上下文 :命令最后的 <路径> 非常重要,它指定了构建时发送给 Docker 守护进程(也就是docker客户端给对应服务端发送进行的镜像制作)的文件目录(通常包含 Dockerfile 和需要复制到镜像中的代码文件)。

演示URL:

首先要知道安装了nginx在宿主机上所以访问对应ip自动默认访问80端口也就是nginx主页:

也就是访问对应ip作为网址,自动跑到这个html目录中:index.html默认就是80,下面配合url方式curl一下:

  • 成功curl到。
  • 网站也是可以的(这也就是为啥nginx可以被使用搭建网站原因,如这个html里)
  • 基于url进行dockerfile构建。
  • 成功构建。

演示-f与--no-cache

  • 说是以当前目录为上下文,但是找不到对应的dockerfile。

下面指明对应dockerfile文件:

  • 成功构建。

对于 --no-cache 使用的话可以看出如果复杂的镜像构建且无前基础,就会变得很慢。

演示-q与--label

之前在arg指令演示过---build-arg了。

  • 成功构建只返回对应对应的id(这里写成两个--label来设置多标签)。
  • 查看镜像对应标签也是成功的。

演示--network

  • 这里指定了构建过程使用宿主机的网络,所以才能https访问到对应的tar包。

五.dockerfile制作优秀实践

首先要知道Dockerfile 镜像构建完全由本机的Docker 守护进程(daemon)负责执行。

  • 使用 .dockerignore:创建此文件来排除构建时不需要的文件,避免发送无用数据,加速构建过程。
  • 多阶段构建 :将编译和运行环境分离,最终镜像只包含运行所需的最小内容,大幅减小镜像体积(但是最后生成的镜像是以最后一个from为主)。
  • 利用构建缓存 :把内容变动少的指令(如安装依赖)放在 Dockerfile 前面,充分利用缓存提升构建速度(此时当频繁修改源代码,再次build的时候就直接不用一直安装gcc耗时间了)。
  • 精选基础镜像:优先选择官方的轻量级基础镜像(如 Alpine、slim 版本),避免使用臃肿的全功能系统镜像。
  • 合并镜像层 :尽量将多条 RUNCOPYADD 指令合并成一条,减少镜像层数。
  • 保持镜像单一功能:一个镜像专注于一个用途,避免制作大而全的复杂镜像(避免镜像融合)。
  • 固定外部依赖 :从外部引入数据或依赖时,使用明确的版本号和持久化地址,确保构建可重复且稳定(如果本机不能上网,http去远端就出问题了下载)。
  • 仅安装必要软件包:只安装应用运行必需的软件包,避免安装任何可有可无的包,以最小化镜像体积。

六.测试需要代码汇总

戳我速看dockerfile等文件

七.本篇小结:

本篇通过对比快照与 Dockerfile 两种镜像构建方式,深入剖析了 Dockerfile 核心指令的功能、语法及实战应用场景。从基础镜像选择、多层合并到多阶段构建,全面阐述了镜像优化策略。同时结合安全规范与生产实践,为开发者提供了从开发到部署的完整容器化解决方案,显著提升应用交付效率与运维可靠性。

相关推荐
分布式存储与RustFS1 天前
MinIO 官方 Docker 镜像被移除:依赖它的项目该怎么办
docker·云原生·devops·对象存储·minio·分布式存储
玉&心1 天前
通过Arthas在线诊断K8S中的内存及JVM等使用情况
docker·k8s·arthas
xing-xing1 天前
Docker容器中Nginx站点根目录网页配置访问
nginx·docker
guo_wen_qiang1 天前
上传本地镜像到harbor中
docker·容器·持续部署
BianHuanShiZhe1 天前
docker常见命令
docker
正经教主1 天前
【FDE系列】阶段2:Day 43:Docker Compose — 多容器一键编排
人工智能·docker·fde
忆~遂愿1 天前
本地片库怎么在外面打开?Plex + cpolar 搭一套可远程访问的私人影音库
docker·容器
Zhu7581 天前
docker环境,vLLM 部署 Qwen3.8-27B
docker·qwen·vllm
溜达的大象1 天前
多台服务器不想上重型监控?用 Beszel 搭一套轻量主机与 Docker 看板
docker