30
2025
04
01:40:13

新手必看!Dockerfile核心指令详解,让你的镜像更专业

Dockerfile是一个自动化创建Docker镜像步骤的文件。它类似于Makefile,是一个配置文件,描述了组装镜像所采取的步骤,自动化了创建Docker镜像的步骤。

要构建镜像,请创建一个名为Dockerfile的文件,Docker可以从Dockerfile读取指令,以自动执行手动创建镜像的步骤。创建Dockerfile后,调用docker build命令,使用包含Dockerfile的目录路径作为参数。

语法    

INSTRUCTION arguments

例如:

FROM image


用法    

docker build .


--运行步骤并提交它们,构建最终镜像。

源代码存储库的路径定义了在哪里可以找到build的上下文。build是由Docker守护进程运行的,而不是CLI。必须将整个上下文传输到守护进程。当上下文被发送到Docker守护进程时,Docker CLI会报告“Sending build context to Docker daemon”( 正在向Docker守护进程发送构建上下文)。

docker build -t repository/tag .


--指定一个存储库和标签,如果构建成功,则保存新镜像。Docker守护进程逐一运行这些步骤,必要时将结果提交到新镜像,然后最终输出新镜像的ID。Docker守护进程会自动清理给定的上下文。    

Docker尽可能重用中间镜像。这大大加快了docker构建过程。

格式    

FROM imageFROM image:tagFROM image@digest


--FROM指令为后续指令设置基础镜像。一个有效的Dockerfile必须以FROM作为其第一条指令。镜像可以是任何有效的镜像。从公共存储库中拉取镜像很容易开始。

--FROM必须是Dockerfile中的第一条非注释指令。

--FROM可能会在单个Dockerfile中多次出现,以创建多个镜像。在每个新的FROM命令之前,记下commit输出的最后一个镜像ID。

--如果FROM指令没有指定标签,Docker会应用latest标签。如果使用的标签不存在,则返回错误。

--如果FROM指令没有指定摘要,Docker会应用latest标签。如果使用的标签不存在,则返回错误。

MAINTAINER    

--MAINTAINER为生成的镜像设置“作者”字段。可用于为用户提供电子邮件或网址以获得支持。    

RUN    

RUN有两种格式:

#在shell中运行该命令- /bin/sh -c

RUN <command>


#可执行格式

RUN ["executable", "param1", "param2"]


--RUN指令在当前镜像之上的新层中执行任何命令,并提交结果。提交的镜像用于Dockerfile中的下一步。

--对RUN指令进行分层和生成提交符合Docker的核心概念,在Docker中,提交成本低廉,容器可以从镜像历史中的任何一点创建。这类似于源代码控制。exec格式可以避免shell字符串的修改。exec表单允许使用不包含/bin/sh的基本镜像运行命令。

请注意,exec表单被解析为JSON数组,这意味着您必须在单词周围使用双引号("),而不是单引号(')。

CMD    

CMD有三种格式:

#可执行格式

CMD ["executable", "param1", "param2"]`


#为ENTRYPOINT提供默认参数

CMD ["param1", "param2"]`


#在shell中运行该命令- /bin/sh -c    

CMD command param1 param2


--Dockerfile中应该只有一个CMD。如果列出了多个CMD,则仅最后一个CMD生效。

CMD的主要目的是为正在执行的容器提供默认值。这些默认值可能包括可执行文件,也可能省略可执行文件。如果它们省略了可执行文件,则必须指定ENTRYPOINT。

在shell或exec格式中使用时,CMD指令设置运行镜像时要执行的命令。

如果使用CMD的shell格式,<command>将在/bin/sh-c中执行:

请注意,exec表单被解析为JSON数组,这意味着您必须在单词周围使用双引号("),而不是单引号(')。

FROM ubuntuCMD echo "This is a test." | wc -


--如果你在没有shell的情况下运行命令,那么你必须将命令表示为JSON数组,并给出可执行文件的完整路径。此数组格式是CMD的首选格式。所有附加参数必须单独表示为数组中的字符串:

FROM ubuntuCMD ["/usr/bin/wc","--help"]


--要使容器每次运行相同的可执行文件,请将ENTRYPOINT与CMD结合使用。

如果用户为docker run指定参数,则指定的命令将覆盖CMD中的默认值。

请勿将RUN与CMD混淆。RUN运行命令并提交结果。CMD在构建时不执行任何操作,但指定了镜像的预期命令。    

LABEL    

LABEL <key>=<value> [<key>=<value> ...]


或者

LABEL <key>[ <value>]LABEL <key>[ <value>]...


LABEL指令将元数据添加到镜像中。标签是一个键值对。要指定一个没有值的LABEL,只需使用一个空字符串。要在LABEL值中包含空格,请像在命令行解析中一样使用引号和短划线。

LABEL com.example.vendor="ACME Incorporated"LABEL com.example.vendor "ACME Incorporated"LABEL com.example.vendor.is-beta ""LABEL com.example.vendor.is-beta=LABEL com.example.vendor.is-beta=""


一个镜像可以有多个标签。要指定多个标签,请用空格分隔每个键值对。

标签是可添加的,包括FROM镜像中的标签。当系统遇到并应用新标签时,新键值会用相同的键值覆盖任何以前的标签。

要显示镜像的标签,请使用docker inspect命令。

STOPSIGNAL    

STOPSIGNAL <signal>


STOPSIGNAL指令设置将发送到容器以退出的系统调用信号。此信号可以是SIG格式的信号名称,例如SIGKILL,也可以是与内核系统调用表中的位置匹配的无符号数,例如9。如果未定义,默认值为SIGTERM。    

每个容器都可以使用docker run和docker create上的--stop-signal标志覆盖镜像的默认stopsignal。

EXPOSE    

EXPOSE <port> [<port>...]


EXPOSE指令通知Docker容器在运行时监听指定的网络端口。Docker使用这些信息通过连接互连容器,并在主机系统上设置端口重定向。

ENV    

ENV <key> <value>


ENV指令将环境变量设置为值<value>。此值将传递给所有未来的RUN、ENTRYPOINT和CMD指令。这在功能上相当于在命令前加上<key>=<value>。当从生成的镜像运行容器时,使用ENV设置的环境变量将保持不变。使用docker inspect检查这些值,并使用docker run --env <key>=<value>更改它们。

请注意,设置“ENV DEIAN_FRONTEND=noninteractive”可能会导致意外后果,因为当容器以交互方式运行时,它会持续存在,就像以下命令一样:docker run -t -i image bash

ADD    

ADD有两种格式:    

ADD <src> <dest>


#当路径带有空格时

ADD ["<src>",... "<dest>"]


ADD指令将新文件、目录或远程文件URL复制到路径<dest>处的容器文件系统。可以指定多个<src>资源,但如果它们是文件或目录,那么它们必须相对于正在构建的源目录(构建的上下文)。<dest>是绝对路径,或相对于WORKDIR的路径,源在目标容器内复制到该路径中。

如果<src>参数是一个可识别的压缩格式(tar、gzip、bzip2等)的本地文件,那么它将在容器文件系统中指定的<dest>处解包。请注意,只有本地压缩文件才会被解包,即URL下载和存档解包功能不能一起使用。

所有新目录都是以模式0755创建的,uid和gid为0。

COPY    

COPY有两种格式:

COPY <src> <dest>


#当路径带有空格时

COPY ["<src>",... "<dest>"]


COPY指令从<src>复制新文件,并将其添加到路径处的容器文件系统中。<src>必须是相对于正在构建的源目录(构建的上下文)或远程文件URL的文件或目录的路径。<dest>是绝对路径,或相对于WORKDIR的路径,源将在目标容器内复制到该路径中。如果复制存档文件,它将完全按照构建上下文中显示的那样放入容器中,而无需尝试解压缩。所有新文件和目录都是使用模式0755创建的,uid和gid为0。    

ENTRYPOINT    

ENTRYPOINT有两种格式:

#可执行格式

ENTRYPOINT ["executable", "param1", "param2"]`


#在shell中运行该命令- /bin/sh -c

ENTRYPOINT command param1 param2


--ENTRYPOINT可帮助您配置可以作为可执行文件运行的容器。当您指定一个ENTRYPOINT时,整个容器会像只运行该可执行文件一样运行。ENTRYPOINT指令添加了一个条目命令,当参数传递给docker run时,该命令不会被覆盖。这与CMD的行为不同。这允许将参数传递给入口点,例如docker run <image> -d将-d参数传递给entrypoint。在ENTRYPOINT JSON数组中指定参数(如上面首选的exec格式),或使用CMD语句指定参数。ENTRYPOINT中的参数不会被docker run参数覆盖。通过CMD指定的参数会被docker run参数覆盖。为ENTRYPOINT指定一个纯字符串,它将在/bin/sh-c中执行,就像CMD指令一样:

FROM ubuntuENTRYPOINT wc -l -


这意味着Dockerfile的镜像总是将stdin作为输入(这就是“-”的意思),并打印行数(这就是“-l”的意思)。要将此设置为可选但默认,请使用CMD:

FROM ubuntuCMD ["-l", "-"]ENTRYPOINT ["/usr/bin/wc"]


VOLUME    

VOLUME ["/data"]


VOLUME指令创建具有指定名称的装载点,并将其标记为保存来自本机主机或其他容器的外部装载卷。

USER    

USER daemon


设置用于运行后续命令的用户名或UID。

USER指令可用于设置组或GID。以下示例均有效:

USER [user | user:group | uid | uid:gid | user:gid | uid:group ]


在设置USER指令之前,指令将以root身份运行。USER指令在Dockerfile中可以使用任意次数,并且只会影响后续命令。

WORKDIR    

WORKDIR /path/to/workdir


WORKDIR指令为后面的RUN、CMD、ENTRYPOINT、COPY和ADD Dockerfile命令设置工作目录。它可以在一个Dockerfile中多次使用。相对路径是相对于前一个WORKDIR指令的路径定义的。例如:

WORKDIR /aWORKDIR bWORKDIR cRUN pwd


在上面的示例中,pwd命令的输出是a/b/c。

ARG    

ARG [=]


ARG指令定义了一个变量,用户可以在构建时使用docker build命令使用--build-arg <varname>=<value>标志将该变量传递给构建器。如果用户指定了一个未在Dockerfile中定义的构建参数,则构建将输出警告。

[Warning] One or more build-args [foo] were not consumed


Dockerfile作者可以通过指定ARG一次来定义单个变量,也可以通过多次指定ARG来定义多个变量。例如,一个有效的Dockerfile:

FROM busyboxARG user1ARG buildno...


Dockerfile作者可以选择为ARG指令指定默认值:

FROM busyboxARG user1=someuserARG buildno=1...


如果ARG值有默认值,并且在构建时没有传递任何值,则构建器将使用默认值。    

ARG变量定义从Dockerfile中定义它的行开始生效,而不是从命令行或其他地方的参数使用开始生效。例如,考虑以下Dockerfile:

1 FROM busybox2 USER ${user:-some_user}3 ARG user4 USER $user...


用户通过调用以下命令构建此文件:

$ docker build --build-arg user=what_user Dockerfile


第2行的USER计算结果为some_USER,因为用户变量在随后的第3行中定义。当定义了用户并在命令行上传递了what_USER值时,第4行的USER计算结果为what_USER。在ARG指令定义变量之前,任何变量的使用都会导致空字符串。

警告:不建议使用构建时变量来传递github密钥、用户凭据等机密。使用docker history命令,镜像的任何用户都可以看到构建时变量值。

您可以使用ARG或ENV指令指定RUN指令可用的变量。使用ENV指令定义的环境变量总是覆盖同名ARG指令。考虑这个带有ENV和ARG指令的Dockerfile。

1 FROM ubuntu2 ARG CONT_IMG_VER3 ENV CONT_IMG_VER=v1.0.04 RUN echo $CONT_IMG_VER


然后,假设此镜像是使用以下命令构建的:

$ docker build --build-arg CONT_IMG_VER=v2.0.1 Dockerfile


在这种情况下,RUN指令使用v1.0.0而不是用户传递的ARG设置v2.0.1。此行为类似于shell脚本,其中局部作用域的变量从其定义点重写作为参数传递或从环境继承的变量。

使用上面的示例,但使用不同的ENV规范,您可以在ARG和ENV指令之间创建更有用的交互:

1 FROM ubuntu2 ARG CONT_IMG_VER3 ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}4 RUN echo $CONT_IMG_VER


与ARG指令不同,ENV值始终保存在构建的镜像中。考虑一个没有--build-arg标志的docker构建:

$ docker build Dockerfile


使用此Dockerfile示例,CONT_IMG_VER仍保留在镜像中,但其值将为v1.0.0,因为它是ENV指令在第3行中设置的默认值。

本例中的变量扩展技术允许您从命令行传递参数,并通过利用ENV指令将其持久化在最终镜像中。变量扩展仅支持有限的一组Dockerfile指令。#environment-replacement

Docker有一组预定义的ARG变量,您可以在不在Dockerfile中使用相应的ARG指令的情况下使用它们。


• HTTP_PROXY• http_proxy• HTTPS_PROXY• https_proxy• FTP_PROXY• ftp_proxy• NO_PROXY• no_proxy• ALL_PROXY• all_proxy


要使用这些,请在命令行中使用--build-arg标志传递它们,例如:


$ docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .


ONBUILD    


ONBUILD [INSTRUCTION]


ONBUILD指令将触发器指令添加到镜像中。触发器将在稍后执行,届时镜像将用作另一个构建的基础。Docker在下游构建的上下文中执行触发器,就像触发器在下游Dockerfile中的FROM指令之后立即存在一样。

您可以将任何构建指令注册为触发器。如果您要定义一个镜像作为构建其他镜像的基础,触发器非常有用。例如,如果您正在定义一个应用程序构建环境或一个使用用户特定配置定制的守护进程。

考虑一个旨在作为可重用python应用程序构建器的镜像。它必须将应用程序源代码添加到特定目录中,并可能需要在此之后调用一个构建脚本。您现在不能只调用ADD和RUN,因为您还没有访问应用程序源代码的权限,而且每个应用程序构建都是不同的。    

--为应用程序开发人员提供一个样板Dockerfile来复制粘贴到他们的应用程序中是低效的、容易出错的,而且很难更新,因为它与特定于应用程序的代码混合在一起。解决方案是使用ONBUILD提前注册指令,以便在下一个构建阶段稍后运行。




推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

本文链接:https://hqyman.cn/post/10994.html 非本站原创文章欢迎转载,原创文章需保留本站地址!

分享到:
打赏





休息一下~~


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

请先 登录 再评论,若不是会员请先 注册

您的IP地址是: