当前位置: 首页 > news >正文

Docker学习笔记(三)Dockerfile

一、什么是Dockerfile

        Dockerfile 是一个用于自动化构建 Docker 镜像的文本文件,其中包含了从一个基础镜像开始,到最终形成所需定制镜像的所有指令集。这个文件中的每一条指令都对应着构建镜像过程中的一个步骤或一层,指导 Docker 如何安装软件、设置环境变量、复制文件、开启端口以及配置运行时的各种参数等。说白了就是可以自定义自己的镜像。

二、使用 Dockerfile 定制镜像

        1.下面以定制一个 ubuntu 镜像

        在根目录下新建一个Dockerfile目录(名字随意),切换到该目录然后编辑一个名为Dockerfile(必须是这个名字)的文件,编写如下代码:

FROM ubuntu:latestWORKDIR /appCOPY . /appRUN apt-get update && apt-get install -y python3ENV MY_VAR="value"EXPOSE 8080CMD ["python3", "app.py"]

过程如下:

 2.指令解析

dockerfile指令大全

Dockerfile 指令

说明

FROM

指定基础镜像,用于后续的指令构建。

MAINTAINER

指定Dockerfile的作者/维护者。

LABEL

添加镜像的元数据,使用键值对的形式。

RUN

在构建过程中在镜像中执行命令。

CMD

指定容器创建时的默认命令。(可以被覆盖)

ENTRYPOINT

设置容器创建时的主要命令。(不可被覆盖)

EXPOSE

声明容器运行时监听的特定网络端口。

ENV

在容器内部设置环境变量。

ADD

将文件、目录或远程URL复制到镜像中。

COPY

将文件或目录复制到镜像中。

VOLUME

为容器创建挂载点或声明卷。

WORKDIR

设置后续指令的工作目录。

USER

指定后续指令的用户上下文。

ARG

定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。

ONBUILD

当该镜像被用作另一个构建过程的基础时,添加触发器。

STOPSIGNAL

设置发送给容器以退出的系统调用信号。

HEALTHCHECK

定义周期性检查容器健康状态的命令。

SHELL

覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。

以下是一 

FROM

        FROM是Dockerfile中的第一个指令,也是一个必须的指令。它用于指定构建新镜像时所基于的基础镜像。基础镜像可以是官方的Docker镜像,也可以是其他人或组织发布在Docker Hub或其他容器注册表中的镜像。

格式:FROM <image>FROM <image>:<tag>
示例:FROM nginx:1.25.1-alpine 默认不写使用latest版本的基础镜像

MAINTAINER

                用于指定镜像的维护者信息。它的作用和用法与LABEL指令类似,用于为镜像添加作者、维护者、联系方式等元数据。

格式:MAINTAINER <name>
示例:MAINTAINER PENG MAINTAINER xxx@qq.com

LABEL

        用于向构建的镜像添加元数据(metadata)。这些元数据以键值对的形式存在,可以用来标注关于镜像的各种信息,比如版本号、作者、创建日期、描述等。元数据对于镜像的管理和追踪非常有用,它们可以帮助用户更好地理解和分类不同的镜像。

格式:LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:LABEL version="1.0" \author="John Doe" \description="This image contains a web server with application XYZ" \release-date="2024-05-15"

RUN

        RUN是Dockerfile中的一个重要指令,用于在镜像中执行命令,以便在构建过程中安装软件包、配置环境、生成文件等。RUN指令执行的命令会在新的镜像层中运行,并且在后续构建中,只有在该层之前的内容发生变化时才会重新运行,利用了Docker的缓存机制,提高了构建速度。RUN指令可以接受多种格式的命令执行方式:Shell 格式:默认情况下,RUN指令使用Shell来执行命令。

shell格式:RUN apt-get update && apt-get install -y python3
Exec格式:RUN ["apt-get", "update"]RUN ["apt-get", "install", "-y", "python3"]

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。可简化为以下格式:

FROM centos
RUN yum -y install wget \&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \&& tar -xvf redis.tar.gz

CMD

        CMD是Dockerfile中的一个重要指令,用于定义容器启动时默认要执行的命令。一个Dockerfile中只能包含一个CMD指令,如果有多个,则只有最后一个CMD指令会生效。CMD指令有两种格式:Shell 格式:使用Shell格式时,命令会在Shell中执行。

shell格式:CMD python app.py
Exec格式: 使用数组格式时,命令不会在Shell中执行,而是直接在容器中执行。CMD ["python", "app.py"]

        使用CMD指令可以为镜像定义一个默认的启动命令,当使用docker run命令启动容器时,如果没有指定其他命令,就会执行CMD中定义的命令。这使得在创建容器时无需手动指定要运行的命令,从而使容器的使用更加简便。如果在docker run命令中指定了其他命令,则会覆盖CMD指令中的默认命令。例如,如果在启动容器时执行以下命令,就会覆盖CMD中定义的默认启动命令:

docker run my_image python script.py

在上面的例子中,容器会运行python script.py命令,而不是默认的CMD指令中定义的命令。

ENTRYPOINT

        ENTRYPOINT是Dockerfile中的一个重要指令,用于配置容器启动时的默认执行命令。它类似于CMD指令,但有一些关键的区别。ENTRYPOINT指令的格式与CMD指令类似,可以使用Shell格式或数组格式,但在使用时,需要注意以下几点:

  1. ENTRYPOINT指令的命令会在容器启动时始终执行,无论在docker run命令中是否指定了其他命令。它不会被覆盖,而是作为容器的主要执行命令。
  2. 如果在docker run命令中指定了其他命令,这些命令将作为ENTRYPOINT指令的参数进行传递。也就是说,ENTRYPOINT指令中的命令将成为执行时的前缀。

下面是一个使用ENTRYPOINT指令的简单示例:

FROM ubuntu:latestENTRYPOINT ["echo", "Hello"]

如果我们构建该镜像并运行容器,不提供其他参数,那么容器启动后将输出 "Hello":

$ docker build -t my_image .
$ docker run my_image
Hello

 如果我们在运行容器时提供了其他参数,那么这些参数将作为ENTRYPOINT指令中命令的参数:

$ docker run my_image "World"
Hello World

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

EXPOSE

       仅仅只是声明端口。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
格式:EXPOSE <端口1> [<端口2>...]

ENV

        设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

格式:ENV <key> <value>ENV <key1>=<value1> <key2>=<value2>...
示例:FROM ubuntu:latest# 设置环境变量ENV MY_NAME John DoeENV APP_HOME /app# 创建目录并设置工作目录RUN mkdir $APP_HOMEWORKDIR $APP_HOME# 复制应用程序到镜像中COPY . .# 在运行时输出环境变量CMD echo "Hello, $MY_NAME"

        在上面的例子中,我们使用了两个ENV指令来设置两个环境变量:MY_NAME和APP_HOME。在镜像构建过程中,这些环境变量会被设置为指定的值。然后,在容器启动时,CMD指令中的命令将使用$MY_NAME环境变量的值输出问候语。在运行容器时,你可以通过docker run命令的-e选项来覆盖环境变量的值。例如:

$ docker run -e MY_NAME="Alice" my_image

上述命令将覆盖默认的MY_NAME环境变量值,容器将输出 "Hello, Alice"。

ARG

        构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

格式:ARG <参数名>[=<默认值>]
示例:FROM ubuntu:latest# 定义构建参数ARG MY_ENV=production# 使用构建参数设置环境变量ENV ENVIRONMENT=$MY_ENV

在上面的例子中,我们通过ARG指令定义了一个名为MY_ENV的构建参数,并设置了其默认值为production。然后,在FROM指令之后,我们使用构建参数设置了一个名为ENVIRONMENT的环境变量。在构建镜像时,可以通过--build-arg选项来指定构建参数的值,例如:

$ docker build --build-arg MY_ENV=development -t my_image .

COPY

        复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]
示例:COPY hom* /mydir/

[--chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

        ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

VOLUME

        VOLUME于声明容器中的挂载点(数据卷)。数据卷是一个特殊的目录,它可以绕过联合文件系统(UnionFS),并在容器间共享数据。VOLUME指令的格式是VOLUME ["/path/to/directory"],其中/path/to/directory是挂载点的路径。可以在一个Dockerfile中使用多个VOLUME指令来声明多个挂载点。

格式:VOLUME ["<路径1>", "<路径2>"...]VOLUME <路径>
示例:FROM ubuntu:latest# 声明两个挂载点VOLUME ["/app/data", "/app/logs"]

在上面的例子中,我们声明了两个挂载点/app/data和/app/logs,这样在运行容器时,可以将这两个挂载点映射到主机的文件系统中,以实现数据持久化和共享。在运行容器时,可以使用-v选项或--mount选项来将主机的目录或数据卷映射到容器的挂载点。例如:

$ docker run -v /host/data:/app/data -v /host/logs:/app/logs my_image

上述命令将主机的/host/data和/host/logs目录分别映射到容器中的/app/data和/app/logs挂载点,实现了主机和容器之间的数据共享。

WORKDIR

        WORKDIR用于设置工作目录,也称为当前工作目录。在容器启动时,进程的当前工作目录将被设置为WORKDIR指令所指定的目录。我们使用WORKDIR指令将工作目录设置为/app,

FROM ubuntu:latest# 设置工作目录
WORKDIR /app# 容器启动时运行的命令
CMD ["python", "app.py"]

         当容器启动时,进程的当前工作目录将自动设置为/app,这样在执行CMD指令时,不需要使用绝对路径来运行python app.py。

USER

        USER用于指定在容器中运行镜像时要使用的非特权用户。默认情况下,Docker容器在启动时以root用户身份运行,这意味着容器内的进程具有最高权限。然而,为了加强安全性,避免潜在的安全风险,最好以非特权用户的身份运行容器中的应用程序。以下是一个简单的示例:

FROM ubuntu:latest# 创建一个新用户并切换到该用户
RUN useradd -ms /bin/bash myuser
USER myuser# 设置工作目录
WORKDIR /app# 复制应用程序到工作目录
COPY . .# 设置环境变量
ENV APP_ENV production# 容器启动时运行的命令
CMD ["python", "app.py"]

        在上面的例子中,我们使用useradd命令创建了一个名为myuser的新用户,并使用-ms /bin/bash选项指定了创建用户时使用的shell。然后,通过USER指令切换到了myuser用户。这样,在容器运行时,进程将以myuser用户的身份运行,而不是以root用户身份。

三、构建镜像

以下是一个简单的Dockerfile示例:

# 使用官方的Ubuntu 20.04镜像作为基础镜像
FROM ubuntu:20.04# 设置工作目录
WORKDIR /app# 复制应用程序到镜像中
COPY . .# 安装应用程序所需的依赖
RUN apt-get update && apt-get install -y python3# 设置环境变量
ENV APP_ENV production# 容器启动时运行的命令
CMD ["python3", "app.py"]

构建镜像:docker build命令:

docker build -t my_image .

-t: 是指定镜像名

        docker build命令会根据Dockerfile的内容,逐条执行其中的指令,并创建一个新的镜像。构建过程会根据每条指令的内容,生成新的镜像层。每条指令都会在上一层的基础上进行修改,最终构建出一个完整的镜像。基于参数构建镜像。

构建完后用命令docker images查看刚刚构建的镜像:

参考文章: 万字长文带你看全网最详细Dockerfile教程-腾讯云开发者社区-腾讯云 (tencent.com) 

相关文章:

Docker学习笔记(三)Dockerfile

一、什么是Dockerfile Dockerfile 是一个用于自动化构建 Docker 镜像的文本文件&#xff0c;其中包含了从一个基础镜像开始&#xff0c;到最终形成所需定制镜像的所有指令集。这个文件中的每一条指令都对应着构建镜像过程中的一个步骤或一层&#xff0c;指导 Docker 如何安装软…...

学懂C#编程:C# 索引器(Indexer)的概念及用法

C#中的索引器&#xff08;Indexer&#xff09;是一种特殊的成员&#xff0c;它允许类或结构的实例像数组那样通过索引来访问其内部的数据。索引器提供了一种灵活的方式来暴露集合或数组类型的内部数据&#xff0c;使得客户端代码可以使用类似于数组下标的语法来访问类的成员&am…...

汇川CodeSysPLC教程03-2-14 与HMI通信

硬件连接 PLC与HMI连接采用何种连接方式&#xff0c;通常是参考双方支持哪些接口。PLC&#xff08;可编程逻辑控制器&#xff09;与HMI&#xff08;人机界面&#xff09;之间的通讯方式主要有以下几种&#xff1a; 串行通讯&#xff08;Serial Communication&#xff09;&…...

centos部署jar包

第一步&#xff1a; 将IDEA中的项目打包为jar,将这个jar文件放到centos服务器上的目录里&#xff0c;我在opt新建api目录&#xff0c;将jar文件放入&#xff0c;如下图&#xff1a; 第二步&#xff1a; 将需要读取的配置文件也放入此目录(其他目录也可以&#xff0c;和脚本中…...

CSS相对定位和绝对定位的区别

CSS相对定位和绝对定位的区别 区别1&#xff1a;相对的对象不同 相对定位是相对于自己绝对定位是相对于离自己最近的有定位的祖先 区别2:是否会脱离文档流 相对定位不会脱离文档流&#xff0c;不会影响其他元素的位置绝对定位会脱离文档流&#xff0c;会影响其他元素的布局 代…...

SpringCloud之nacos共享配置文件实现多数据源灵活切换

目录 前言 1.引入Springboot相关的aop切面依赖 2.创建自定义注解DataSourceKey 3.创建对ThreadLocal类 4.创建aop切面 5.创建动态数据源类 6.创建多数据库连接配置类 7.关键代码讲解 8.nacos主要配置 前言 通过Spring AOP&#xff08;面向切面编程&#xff09;的功能来动…...

原生小程序生成二维码方法之一

效果图&#xff1a; 第一步&#xff1a;下载对应的包并构建&#xff08;工具---》构建npm&#xff09; npm install weapp-qrcode --save 第二步&#xff1a;在wxml页面声明canvas <canvas style"width: 200px; height: 200px;margin:0 auto;" canvas-id"myQ…...

Kubernetes k8s Pod容器 探针 健康探测

目录 Pod容器健康探测 为什么要对容器做探测&#xff1f; 启动探测startupprobe 存活性探测livenessProbe 就绪性探测readinessProbe ReadinessProbe LivenessProbe startupProbe配合使用示例一般程序中需要设置三种探针结合使用&#xff0c;并且也要结合实际情况&#xff…...

Conformal low power-2.电源感知等效性检查

电源感知等效性检查 ■ 第24页&#xff1a;电源感知等效性检查概述 ■ 第24页&#xff1a;启动低功耗&#xff08;等效性检查&#xff09;软件 ■ 第25页&#xff1a;电源感知等效性检查流程 ■ 第28页&#xff1a;电源感知等效性检查示例Do文件 电源感知等效性检查概述…...

【密码学】从有限状态自动机到密钥流生成器

本文是对流密码内容的拓展&#xff0c;在流密码中种子密钥通过一个伪随机数生成器产生一个与明文等长的伪随机密钥流。而本文的内容就是在回答这样两个问题&#xff1a; 伪随机密钥流是如何生成的&#xff1f;流密码、流密钥生成器和有限状态自动机之间是什么关系&#xff1f;…...

3.相机标定原理及代码实现(opencv)

1.相机标定原理 相机参数的确定过程就叫做相机标定。 1.1 四大坐标系及关系 &#xff08;1&#xff09;像素坐标系&#xff08;单位&#xff1a;像素&#xff08;pixel&#xff09;&#xff09; 像素坐标系是指相机拍到的图片的坐标系&#xff0c;以图片的左上角为坐标原点&a…...

Centos7 安装Docker步骤及报错信息(不敢说最全,但是很全)

一、操作系统要求&#xff1a; 要安装Docker Engine&#xff0c;您需要CentOS 7及以上的维护版本。存档版本不受支持或测试。必须启用centos临时存储库。默认情况下&#xff0c;此存储库已启用&#xff0c;但如果已禁用&#xff0c;则需要重新启用它。建议使用overlay2存储驱动…...

【C语言】符号优先级详解

C语言符号优先级详细解析 在C语言中&#xff0c;不同的运算符具有不同的优先级和结合性&#xff0c;这决定了在表达式中运算符的计算顺序。理解这些优先级和结合性是正确编写和理解C语言程序的基础。本文将详细解析C语言中的符号优先级&#xff0c;包括各类运算符的优先级、结…...

天翼云高级运维工程师202407回忆题库 最新出炉

备考天翼云高级运维工程师 必须备考天翼云 之前觉得外企牛批 然后民企&#xff0c;拔地而起&#xff0c;民企也不错&#xff0c;工资高&#xff0c;有钱途 现在看来看去&#xff0c;还是国企好&#xff0c;体制内的&#xff0c;有保障&#xff0c;树大根深 有必要备考下天…...

在Python中什么是上下文管理器以及如何使用with语句来管理资源

什么是上下文管理器&#xff1f; 在Python中&#xff0c;上下文管理器&#xff08;Context Manager&#xff09;是一种支持with语句的协议&#xff0c;允许对象管理资源&#xff0c;如文件、线程锁的获取和释放、数据库连接等。上下文管理器负责资源的分配和释放&#xff0c;确…...

(四)、python程序--贪吃蛇游戏

一、绪论 贪吃蛇游戏。 已实现功能&#xff1a; 1、上下左右移动&#xff1b; 2、吃食物&#xff0c;随机生成食物&#xff1b; 3、碰撞检测&#xff0c;判断是否游戏结束。 二、代码分享 1、main.py import pygame import sys import food as c_food import snake as c…...

什么是DNS欺骗

DNS欺骗&#xff08;DNS Spoofing&#xff09;&#xff0c;也称为DNS缓存中毒&#xff08;DNS Cache Poisoning&#xff09;&#xff0c;是一种网络攻击形式&#xff0c;攻击者通过操纵DNS记录&#xff0c;将用户重定向到一个伪造的、恶意的网站。这些恶意网站可能看起来与用户…...

C++实现对结构体信息排序

思路解读&#xff1a; 定义结构体 Student: 结构体 Student 用来表示学生信息&#xff0c;包含两个成员变量&#xff1a;name&#xff08;学生姓名&#xff09;和 score&#xff08;学生分数&#xff09;。Student 结构体定义了一个构造函数&#xff0c;用于初始化 name 和 sco…...

[CTF]-PWN:House of Cat堆题型综合解析

原理&#xff1a; 调用顺序&#xff1a; exit->_IO_wfile_jumps->_IO_wfile_seekoff->_IO_switch_to_wget_mode _IO_wfile_seekoff源码&#xff1a; off64_t _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode) {off64_t result;off64_t delta, new…...

18.按键消抖模块设计(使用状态机,独热码编码)

&#xff08;1&#xff09;设计意义&#xff1a;按键消抖主要针对的时机械弹性开关&#xff0c;当机械触点断开、闭合时&#xff0c;由于机械触点的弹性作用&#xff0c;一个按键开关在闭合时不会马上稳定地接通&#xff0c;在断开时也不会一下子就断开。因而在闭合以及断开的瞬…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...