Docker镜像构建指南:Dockerfile语法与docker build命令全解析

Docker镜像构建指南:Dockerfile语法与docker build命令全解析

文章目录

一、镜像制作简介

Docker镜像能将应用程序及其所有依赖(如库、配置、运行时环境等)打包成一个标准化的、可移植的文件,确保应用在任何支持Docker的环境中都能以相同方式运行,从而解决"在我这能跑,到你那却不行"的环境一致性问题,同时简化部署流程、提高扩展效率,并通过容器化实现资源隔离与轻量化管理,让应用的开发、测试和生产环境保持统一,大幅降低跨环境部署的复杂度和出错概率。

制作镜像主要有两种方式:

  • 使用docker commit指令:基于运行中的容器手动创建镜像,这种方式操作简单但缺乏可重复性,镜像构建过程难以追溯和维护,不推荐用于生产环境。
  • 使用Dockerfile文件:通过编写结构化的文本文件定义镜像构建步骤,支持版本控制、自动化构建和精确配置,能清晰记录镜像制作过程,便于团队协作与迭代优化,是推荐的标准做法。

相比docker commit,使用 Dockerfile 构建镜像是绝对的主流做法,核心优势如下:

1. 自动化 & 可重复

  • 文本文件定义流程,docker build 一键生成。
  • 环境、配置、步骤完全一致,杜绝“在我这好使”的问题。

2. 透明 & 可追溯

  • 所有构建步骤(装了啥、改了啥)一目了然。
  • 文件可存入 Git,谁改了哪里,历史可查。

3. 高效 & 快速

  • 利用分层缓存:只重建变更的步骤,大幅提升构建速度。

4. 易维护 & 最佳实践

  • 轻松实施优化(如用小体积基础镜像、合并指令)。
  • 结构清晰,易于理解和修改。

5. 天生适合 CI/CD

  • 完美集成自动化流程,实现代码提交后自动构建、测试、部署。

二、Dockerfile文件配置

Dockerfile 就是镜像的蓝图,Dockerfile与镜像的关系如同图纸与房子的关系

在这里插入图片描述


Dockerfile格式:

# Comment INSTRUCTION arguments 

2.1 常用命令清单

官方地址:https://docs.docker.com/reference/dockerfile/

  • FROM:构建镜像基于哪个镜像,也就是基础镜像
  • LABEL:为镜像添加元数据
  • COPY:拷贝文件或目录到镜像中,跟 ADD 类似,但不具备自动下载或解压的功能
  • ADD:拷贝文件或目录到镜像中,如果是 URL 或压缩包便会自动下载或自动解压
  • WORKDIR:指定工作目录
  • RUN:指定 docker build 过程中运行的程序
  • VOLUME:指定容器挂载点
  • EXPOSE:声明容器的服务端口(仅仅是声明)
  • ENV:设置环境变量
  • CMD:运行容器时执行的命令
  • ENTRYPOINT:运行容器时程序入口
  • ARG:指定构建时的参数
  • USER:指定当前用户
  • HEALTHCHECK:健康检测指令

2.2 命令详解

功能:

  • FROM 指令用于为镜像文件构建过程指定基础镜像,后续的指令运行于此基础镜像所提供的运行环境;

注意事项:

  • FROM 指令必须是 Dockerfile 中非注释行或者 ARG 之后的第一个指令
  • 实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build 会在 docker 主机上查找指定的镜像文件,在其不存在时,则会自动从 Docker 的公共库 pull 镜像下来。如果找不到指定的镜像文件,docker build 会返回一个错误信息;
  • FROM 可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile 中创建多个镜像,或将一个构建阶段作为另一个的依赖;
  • 如果 FROM 语句没有指定镜像标签,则默认使用 latest 标签。

语法:

FROM [--platform=<platform>]<image>[AS <name>] FROM [--platform=<platform>]<image>[:<tag>][AS <name>] FROM [--platform=<platform>]<image>[@<digest>][AS <name>]

参数:

  • <platform>:构建的 cpu 架构,如 linux/amd64, linux/arm64, windows/amd64
  • <image>: 指定作为 base image 的名称;
  • <tag>: base image 的标签,省略时默认 latest
  • <digest>: 是镜像的哈希码;
  • AS <name>: 指定构建步骤的名称,配合 COPY --from=<name> 可以完成多级构建

示例:

在这里插入图片描述
  • 注意:可在一个 Dockerfile 中多次使用FROM指令,每个FROM指令开启一个新的构建阶段。每个阶段都可以有自己的安装、配置和构建步骤。后面的构建阶段可以从前面的构建阶段中选择性地复制所需的文件或目录。即“多阶段构建”

LABEL
功能:

  • 为镜像添加元数据

语法:

LABEL <key>=<value> <key>=<value> <key>=<value> ... 

示例:

FROM ubuntu:22.04 as buildstage1 LABEL version="1.0" desc="create by bit" 

COPY
功能:

  • 用于从 docker 主机复制新文件或者目录至创建的新镜像指定路径中。

语法:

COPY [--chown=<user>:<group>]<src>... <dest> COPY [--chown=<user>:<group>]["<src>",... "<dest>"]

参数:

  • <src>:要复制的源文件或目录,支持使用通配符;
  • <dest>:目标路径,即正在创建的 image 的文件系统路径;建议<dest>使用绝对路径,否则,COPY 指定以 WORKDIR 为当前路径
    在路径中有空白字符时,通常使用第 2 种格式;
  • --chown:修改用户和组
  • --from <name>可选项:可以从之前构建的步骤中拷贝内容,结合 FROM ... AS <name>往往用作多级构建,后续我们有实战课专门完成多级构建

注意:

  • <src>必须是 build 上下文中的路径,不能是其父目录中的文件;
  • 如果<src>是目录,则其内部文件或子目录会被递归复制,<src>目录自身不会被复制
  • 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以 / 结尾;
  • 如果<dest>事先不存在,它将会被自动创建,这包括父目录路径。

示例:

在这里插入图片描述


效果:

在这里插入图片描述

ENV
功能:

  • 用于为镜像定义所需的环境变量,并可被 Dockerfile 文件中位于其后的其它指令(如 ENV、ADD、COPY 等)所调用
  • 调用格式为 $variable_name${variable_name}
    语法:
ENV <key>=<value>... 

示例:

在这里插入图片描述


效果:

在这里插入图片描述

与ENV配合使用:

ENV MYROOTDIR=/data/web/html/ COPY ./index.html ${MYROOTDIR}

WORKDIR
功能:

  • 为 Dockerfile 中所有的 RUNCMDENTRYPOINTCOPYADD 指定设定工作目录,相当于cd到一个目录然后执行指令
    语法:
WORKDIR /path/to/workdir 

注意:

  • 默认的工作目录是 /
  • 如果提供了相对路径,它将相对于前一条 WORKDIR 指令的路径。
  • WORKDIR 指令可以解析先前使用设置的环境变量 ENV

示例:

在这里插入图片描述


效果:

在这里插入图片描述
  • 注意:在 Dockerfile 中,如果存在多个 WORKDIR 指令,在后续的 WORKDIR 指令出现之前,所有需要指定工作目录的指令(如 RUN、CMD、ENTRYPOINT、COPY、ADD 等)都会以上一个 WORKDIR 所设置的路径作为工作目录。

ADD
功能:

  • ADD 指令类似于 COPY 指令,ADD 支持使用 TAR 文件和 URL 路径,会自动完成解压和下载,而copy不支持这个功能
    语法:
ADD [--chown=<user>:<group>]<src>... <dest> ADD [--chown=<user>:<group>]["<src>",... "<dest>"]

参数:

  • <src>:要复制的源文件或目录,支持使用通配符;
  • <dest>:目标路径,即正在创建的 image 的文件系统路径;建议<dest>使用绝对路径,否则,ADD 指定以 WORKDIR 为起始路径;在路径中有空白字符时,通常使用第 2 种格式;
  • --chown:修改用户和组

示例:

在这里插入图片描述


效果:

在这里插入图片描述

如果是本地下载tar,然后给容器会自动解压。如果是远端则不会。

RUN

功能:

  • 用于指定 docker build 过程中运行的程序,其可以是任何命令

语法:

#shell form RUN <command>#exec form RUN ["executable", "param1", "param2"]

参数:

  • 第一种格式中,<command>通常是一个 shell 命令,且以/bin/sh -c来运行它,Windows 默认为 cmd /S /C。如果一个脚本 test.sh 不能自己执行,必须要 /bin/sh -c test.sh 的方式来执行,那么,如果使用 RUN 的 shell 形式,最后得到的命令相当于:
/bin/sh -c "/bin/sh -c 'test.sh'"
  • 第二种语法格式中的参数是一个 JSON 格式的数组,其中<executable>为要运行的命令,后面的 <paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以/bin/sh -c来发起,因此常见的 shell 操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此 shell 特性的话,可以将其替换为类似下面的格式。
RUN ["/bin/bash", "-c", "<executable>", "<param1>"]

示例:

在这里插入图片描述


注意:多使用&&把指令放在同一个RUN,减少层

CMD

功能:

  • 类似于 RUN 指令,CMD 指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
  • RUN 指令运行于映像文件构建过程中,而 CMD 指令运行于基于 Dockerfile 构建出的新映像文件启动一个容器时
  • CMD 指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD 指定的命令其可以被 docker run 的命令行选项所覆盖
  • Dockerfile 中可以存在多个 CMD 指令,但仅最后一个会生效

语法:

CMD ["executable","param1","param2"](exec form, this is the preferred form) CMD ["param1","param2"](as default parameters to ENTRYPOINT) CMD command param1 param2 (shell form)

注意:

  • 第二种则用于为 ENTRYPOINT 指令提供默认参数
  • json 数组中,要使用双引号,单引号会出错

示例:

CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

ENTRYPOINT
功能:

  • 用于指定容器的启动入口

语法:

#exec form ENTRYPOINT ["executable", "param1", "param2"]# shell form ENTRYPOINT command param1 param2 

参数:

  • json 数组中,要使用双引号,单引号会出错

注意:ENTRYPOINT与CMD功能类似,但ENTRYPOINT不会被docker run指令完全覆盖,docker run后面的参数会作为ENTRYPOINT的参数。

示例:
test:v0.7使用CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
test:v0.8使用ENTRYPOINT ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

EXPOSE

功能:

  • 用于为容器声明打开指定要监听的端口以实现与外部通信
  • EXPOSE 指令实际上并不发布端口。它充当构建图像的人和运行容器的人之间的一种文档,关于要发布哪些端口。要在运行容器时实际发布端口,使用 -p 参数发布和映射一个或多个端口,或者使用 -P flag 发布所有暴露的端口并将它们映射宿主机端口。

语法:

EXPOSE <port>[<port>/<protocol>...]

参数:

  • <protocol>:tcp/udp 协议
  • <port>:端口

示例:

EXPOSE 80/tcp 

ARG

功能:

  • ARG 指令类似 ENV,定义了一个变量;区别于 ENV:用户可以在构建时 docker build --build-arg <varname> = <value> 进行对变量的修改;ENV 不可以;
  • 如果用户指定了未在 Dockerfile 中定义的构建参数,那么构建输出警告。

语法:

ARG <name>[=<default value>]

注意:

  • Dockerfile 可以包含一个或多个 ARG 指令
  • ARG 支持指定默认值
  • 使用范围:定义之后才能使用,定义之前为空,如下面的案例,执行命令 docker build --build-arg username=what_user . 第二行计算结果为 some_user,不是我们指定的 build-arg 中的参数值 what_user

注意:ARG和ENV同时存在时,ENV会覆盖ARG

示例:
Dockerfile文件

ARG SYSVERSION=22.04 FROM ubuntu:${SYSVERSION}

构建时可以更改变量从而更改Ubuntu版本:

docker build -t test:v0.9 --build-arg SYSVERSION=22.10

VOLUME
功能:

  • 用于在 image 中创建一个挂载点目录
  • 通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。

语法:

VOLUME <mountpoint> VOLUME ["<mountpoint>"]

参数:

  • mountpoint: 挂载点目录

注意:

  • 如果挂载点目录路径下此前有文件存在,docker run 命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
  • 其实 VOLUME 指令只是起到了声明容器中的目录作为匿名卷,但是并没有将匿名卷绑定到宿主机指定目录的功能。
  • volume 只是指定了一个目录,用以在用户忘记启动时指定 -v 参数也可以保证容器的正常运行。比如 mysql,你不能说用户启动时没有指定 -v,然后删了容器,就把 mysql 的数据文件都删了,那样生产上是会出大事故的,所以 mysqldockerfile 里面就需要配置 volume,这样即使用户没有指定 -v,容器被删后也不会导致数据文件都不在了。还是可以恢复的。
  • volume-v 指令一样,容器被删除以后映射在主机上的文件不会被删除。
  • 如果 -vvolume 指定了同一个位置,会以 -v 设定的目录为准,其实 volume 指令的设定的目的就是为了避免用户忘记指定 -v 的时候导致的数据丢失,那么如果用户指定了 -v,自然而然就不需要 volume 指定的位置了。

示例:

VOLUME ["/data1"]

USER

功能:

  • 用于指定运行 image 时的或运行 Dockerfile 中任何 RUNCMDENTRYPOINT 指令定的程序时的用户名或 UID
  • 默认情况下,container 的运行身份为 root 用户
    语法:
USER<user>[:<group>]USER<UID>[:<GID>]

参数:

  • user: 用户
  • group: 用户组
  • uid: 用户 id
  • gid: 组 id

注意:

  • <UID>可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则将运行失败

示例:

USER root:root RUN groupadd mysql RUN useradd mysql -g mysql USER mysql:mysql RUN whoami> /tmp/user.txt 

HEALTHCHECK

功能:

  • HEALTHCHECK 指令告诉 Docker 如何测试容器以检查它是否仍在工作。
  • 即使服务器进程仍在运行,这也可以检测出陷入无限循环且无法处理新连接的 Web 服务器等情况。

语法:

HEALTHCHECK [OPTIONS] CMD command(check container health by running a command inside the container) HEALTHCHECK NONE (disable any healthcheck inherited from the base image)

OPTIONS 选项参数:

  • --interval=DURATION (default: 30s):每隔多长时间探测一次,默认 30 秒
  • --timeout= DURATION (default: 30s):服务响应超时时长,默认 30 秒
  • --start-period= DURATION (default: 0s):服务启动多久后开始探测,默认 0 秒
  • --retries=N (default: 3):认为检测失败几次为宕机,默认 3 次

返回值:

  • 0:容器成功是健康的,随时可以使用
  • 1:不健康的容器无法正常工作
  • 2:保留不使用此退出代码

示例:

FROM nginx:1.24.0 HEALTHCHECK --interval=5s --timeout=3s \ CMD curl -fs http://localhost/ ||exit1

三、docker build 指令

功能:

  • docker build 命令用于使用 Dockerfile 创建镜像。

语法:

docker build [OPTIONS] PATH | URL | - 

关键参数:

  • --build-arg=[]:设置镜像创建时的变量;
  • -f:指定要使用的 Dockerfile 路径;
  • --label=[]:设置镜像使用的元数据;
  • --no-cache:创建镜像的过程不使用缓存;
  • --pull:尝试去更新镜像的新版本;
  • --quiet, -q:安静模式,成功后只输出镜像 ID;
  • --tag, -t:镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
  • --network:默认 default。在构建期间设置 RUN 指令的网络模式

Read more

安装 启动 使用 Neo4j的超详细教程

安装 启动 使用 Neo4j的超详细教程

最近在做一个基于知识图谱的智能生成项目。需要用到Neo4j图数据库。写这篇文章记录一下Neo4j的安装及其使用。 一.Neo4j的安装 1.首先安装JDK,配环境变量。(参照网上教程,很多) Neo4j是基于Java的图形数据库,运行Neo4j需要启动JVM进程,因此必须安装JAVA SE的JDK。从Oracle官方网站下载 Java SE JDK。我使用的版本是JDK1.8 2.官网上安装neo4j。 官方网址:https://neo4j.com/deployment-center/  在官网上下载对应版本。Neo4j应用程序有如下主要的目录结构: bin目录:用于存储Neo4j的可执行程序; conf目录:用于控制Neo4j启动的配置文件; data目录:用于存储核心数据库文件; plugins目录:用于存储Neo4j的插件; 3.配置环境变量 创建主目录环境变量NEO4J_HOME,并把主目录设置为变量值。复制具体的neo4j文件地址作为变量值。 配置文档存储在conf目录下,Neo4j通过配置文件neo4j.conf控制服务器的工作。默认情况下,不需

企业微信群机器人Webhook配置全攻略:从创建到发送消息的完整流程

企业微信群机器人Webhook配置全攻略:从创建到发送消息的完整流程 在数字化办公日益普及的今天,企业微信作为国内领先的企业级通讯工具,其群机器人功能为团队协作带来了极大的便利。本文将手把手教你如何从零开始配置企业微信群机器人Webhook,实现自动化消息推送,提升团队沟通效率。 1. 准备工作与环境配置 在开始创建机器人之前,需要确保满足以下基本条件: * 企业微信账号:拥有有效的企业微信管理员或成员账号 * 群聊条件:至少包含3名成员的群聊(这是创建机器人的最低人数要求) * 网络环境:能够正常访问企业微信服务器 提示:如果是企业管理员,建议先在"企业微信管理后台"确认机器人功能是否已对企业开放。某些企业可能出于安全考虑会限制此功能。 2. 创建群机器人 2.1 添加机器人到群聊 1. 打开企业微信客户端,进入目标群聊 2. 点击右上角的群菜单按钮(通常显示为"..."或"⋮") 3. 选择"添加群机器人"选项 4.

Flowise物联网融合:与智能家居设备联动的应用设想

Flowise物联网融合:与智能家居设备联动的应用设想 1. Flowise:让AI工作流变得像搭积木一样简单 Flowise 是一个真正把“AI平民化”落地的工具。它不像传统开发那样需要写几十行 LangChain 代码、配置向量库、调试提示词模板,而是把所有这些能力打包成一个个可拖拽的节点——就像小时候玩乐高,你不需要懂塑料怎么合成,只要知道哪块该拼在哪,就能搭出一座城堡。 它诞生于2023年,短短一年就收获了45.6k GitHub Stars,MIT协议开源,意味着你可以放心把它用在公司内部系统里,甚至嵌入到客户交付的产品中,完全不用担心授权问题。最打动人的不是它的技术多炫酷,而是它真的“不挑人”:产品经理能搭出知识库问答机器人,运营同学能配出自动抓取竞品文案的Agent,连刚学Python两周的实习生,也能在5分钟内跑通一个本地大模型的RAG流程。 它的核心逻辑很朴素:把LangChain里那些抽象概念——比如LLM调用、文档切分、向量检索、工具调用——变成画布上看得见、摸得着的方块。你拖一个“Ollama LLM”节点,再拖一个“Chroma Vector

OpenClaw配置Bot接入飞书机器人+Kimi2.5

OpenClaw配置Bot接入飞书机器人+Kimi2.5

上一篇文章写了Ubuntu_24.04下安装OpenClaw的过程,这篇文档记录一下接入飞书机器+Kimi2.5。 准备工作 飞书 创建飞书机器人 访问飞书开放平台:https://open.feishu.cn/app,点击创建应用: 填写应用名称和描述后就直接创建: 复制App ID 和 App Secret 创建成功后,在“凭证与基础信息”中找到 App ID 和 App Secret,把这2个信息复制记录下来,后面需要配置到openclaw中 配置权限 点击【权限管理】→【开通权限】 或使用【批量导入/导出权限】,选择导入,输入以下内容,如下图 点击【下一步,确认新增权限】即可开通所需要的权限。 配置事件与回调 说明:这一步的配置需要先讲AppId和AppSecret配置到openclaw成功之后再设置订阅方式,