Dockerfile指令

本文详细介绍了Dockerfile的各种指令,包括FORMAT、FROM、ARG、RUN、CMD、LABEL、EXPOSE、ENV、ADD、COPY、VOLUME、USER、WORKDIR、ONBUILD、ENTRYPOINT、HEALTHCHECK和STOPSIGNAL等,帮助读者理解如何构建和配置Docker镜像。Dockerfile支持定义环境变量、添加和复制文件、设置工作目录、指定启动命令以及健康检查等,是构建Docker镜像的关键文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考链接 https://docs.docker.com/engine/reference/builder/

FORMAT

dockerfile的指令不区分大小写,但根据约定应该大写,以便于轻松的和参数进行区分

dockerfile必须以FROM指令或者解析器指令,注释,全局ARG开始。FROM之前只能有一个或者多个ARG指令,用于声明dockerfile中FROM行需要使用的参数。

docker将以#开头的行视为注释,除非该行是有效的解析器指令。行内的#统一被当作参数处理。

为了向后兼容,注释和指令前的空格会被忽略,但不建议保留非必要的空格,指令中的空格不会被忽略

解析器指令

解析器指令是可选的,会影响dockerfile中后续行的处理方式,不回生成新的层,也不会显示为构建步骤。单个解析器指令只能使用一次,一旦处理过注释,空行,解析器指令,docker就不会再查找解析器指令,会将所有内容是为注释,不会去尝试验证是否可能是解析器指令,因此解析器指令应该位于dockerfile最顶部。

解析器指令不区分大小写,约定俗成的使用小写,同时,解析器指令后约定包含一个空行,不支持换行符。

支持以下解析器指令:

syntax

escape

syntax

此功能仅在buildkit时可用,经典生成器时会被忽略 参考 Custom Dockerfile syntax | Docker Documentation

escape

escape指令用于转义dockerfile中的字符,不指定默认为\

# escape=\ (backslash)

# escape=` (backtick)

环境变量

ENV声明环境变量,dockerfile中的环境变量用$variavle ${variable_name}表示

大括号通常用于解决没有空格的变量名称问题,例如${foo}_bar. 同时大括号的语法也支持一些标准bash修饰符。

${variable:-word}
如果设置了该变量,结果是变量值,如果没设置变量,结果默认为该单词
${variable:+word}
如果设置了该变量,结果默认为该单词,如果没设置,结果为空字符串
word可以是任何字符串,包括其他环境变量

在变量前添加\可以将变量转换为文本,而不是引用这个变量的值

\$foo -----$foo
\${foo} ----- ${foo}

FROM busybox
ENV FOO=/bar
WORKDIR ${FOO}       # WORKDIR /bar
ADD . $FOO           # ADD . /bar
COPY \$FOO /quux     # COPY $FOO /quux

 onbuild 配合环境变量,可以替换整个指令中的变量值

最终def的值时hello,ghi的值时bye,因为def参数之前执行的一条命令中abc的值是hello,对abc的重新赋值还未生效

ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc

.dockerignore

在docker命令行界面CLI将上下文发送到docker守护程序之前,会先查找dockerigonre中的文件,进行匹配,排除符合匹配规则的文件。这样可以避免将大型文件,敏感文件,或不必要的文件发送的守护进程。匹配使用go的文件路径,除此之外,docker还支持**的匹配(**匹配任意数量的目录)。

以!开头的行可以用于特殊处理要排除的项。

甚至可以通过.dockerignore文件排除dockerfile和dockerignore,这些文件仍旧会被发送到守护进程,因为需要用来完成其工作,但add copy不会将他们复制到镜像。

因为历史原因,匹配模式.会被忽略

*/temp*
根目录下的任何子目录中以temp开头的文件和目录
*/*/temp*
根目录下两级中temp开头的文件和目录
temp?
根目录中名称为temp开头且有一个字符的temp文件和目录 /tempa /tempb
**/*.go
所有目录中找到以.go结尾的文件
*.md
! readme.md
排除出了readme以外所有md文件

FROM

FROM [--platform=<platform>] <image> [AS <name>]

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

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

FROM ubuntu:16.04

FROM ubuntu:16.04 as stage1

from指令用于初始化新的构建阶段,并未后续指令设置基础镜像,有效的dockerfile必须以from开头(注释和用于from的arg除外)。

from可以在单个dockerfile中多次出现,以创建多个镜像或不同构建阶段。

每个from之前都会清除由先前指令创建的任何状态。

可以将as参数添加到from指令中,以便于标记镜像别名,在后续的from和copy from中引用。

tag可以省略,默认使用latest,没找到会报错。

--platform可以用来制定镜像平台,eg linux/amd64, linux/arm64, windows.amd64。默认情况下使用生成请求的目标platform。

ARG

ARG <name>[=<default value>]
定义用户可以在构建时使用的变量,之后值会被传给--build-arg <varname>=<value> 构建器,如果用户指定的构建参数未在dockerfile中定义,会输出警告

arg可以包含默认值,如果arg包含默认值,且生成时没有传新值,会使用默认值

arg从定义的行开始生效,到当前构建阶段结束失效,因此多阶段构建中,如果需要使用,每个阶段都必须要包含arg

arg和env同名的变量,env会始终覆盖arg的

FROM busybox
ARG user1=someuser
ARG buildno=1

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER

docker build --build-arg CONT_IMG_VER=v2.0.1 .
# 会使用env的值

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER

docker build .
# 值为1.0.0 同时因为env值始终保存在构建的镜像中,所以不需要--build arg
# 变量拓展使允许从命令行传递参数,并通过env将他们持久化到最终镜像中
 

预定义的arg

Docker有一组预定义的ARG变量,您可以在Dockerfile中使用这些变量,而无需相应的ARG指令。

要使用这些,请在命令行上使用--build arg时传递值

HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
ALL_PROXY
all_proxy

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

默认的,这样预订一变量不保存在docker history中,也不会有缓存,避免意外泄漏敏感信息。修改值不会使缓存失效。

如果需要重写该行为,在dockerfile中显示的添加ARG HTTP_PROXY,但这样将会保留在docker histpry中,更改值会是构建缓存失效

全局范围的arg

buildkit后端时可用功能。docker预定义的一组值,可以在构建时使用--platform指定

这些参数是在全局范围内定义的,因此在构建阶段或RUN命令中不会自动使用。若要在构建阶段内公开这些参数之一,请重新定义它而不使用值。

TARGETPLATFORM - platform of the build result. Eg linux/amd64, linux/arm/v7, windows/amd64.
TARGETOS - OS component of TARGETPLATFORM
TARGETARCH - architecture component of TARGETPLATFORM
TARGETVARIANT - variant component of TARGETPLATFORM
BUILDPLATFORM - platform of the node performing the build.
BUILDOS - OS component of BUILDPLATFORM
BUILDARCH - architecture component of BUILDPLATFORM
BUILDVARIANT - variant component of BUILDPLATFORM

FROM alpine
ARG TARGETPLATFORM
RUN echo "I'm building for $TARGETPLATFORM"

ARG变量不会像ENV变量一样持久化到构建的图像中。然而,ARG变量确实以类似的方式影响构建缓存。

如果Dockerfile定义了一个ARG变量,该变量的值与之前的构建时的值不同,那么在第一次使用时会发生“缓存未命中”cache miss。特别是,ARG指令后面的所有RUN指令都隐式使用ARG变量(作为环境变量),因此可能导致缓存未命中。(?)

除非Dockerfile中有匹配的ARG语句,否则所有预定义的ARG变量都可以免于缓存。

arg与from的交互

from指令支持第一个from之前出现的任何arg指令声明的变量

FROM CODE_VERSION=latest
FROM base:${CODE-VERSION}
CMD /code/run-app

FROM ${CODE-VERSION}
CMD /code/run-extras

 在from之前声明的arg在构建阶段之外,因此不能在from之后的任何指令中使用,要想使用第一个from之前的声明的arg默认值,请在构建阶段中再次声明,但不带值

ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version

RUN

run可以使用shell和exec两种格式。run指令在dockerfile构建时生成新并提交。

shell RUN <command>

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

在shell格式中,可以使用\ 续行

exec形式解析为json数组,意味着必须在单词周围使用双引号,而不是单引号

在json格式中,有必要对\进行转义,尤其是对于反斜杠作为路径分隔符的windows。

RUN ["c:\windows\system32\tasklist.exe"]   ❌

RUN ["c:\\windows\\system32\\tasklist.exe"]   ✅

run指令的缓存在下次构建期间不会自动失效,RUN ape-get这样的指令缓存在下次构建期间可以重用。如果不需要缓存,使用--no-cache使缓存失效。

run的缓存对于add和copy是无效的。

RUN --mount

--mount=[type=<TYPE>][,option=<value>[,option=<value>]...]

允许创建构建是可访问的文件挂载系统。可以用于

1. 为主机文件系统或其他构建阶段创建绑定挂载(?)

2. 访问构建secrets或ssh socket

3. 使用永久包管理缓存

mount type:

bind: 默认值,绑定挂载上下文目录(只读)

 具体参数的使用情参考官网。https://docs.docker.com/engine/reference/builder/

RUN --network

--network=<TYPE>

指定命令在那个网络环境中运行

 RUN --security

还未在稳定的docker版本中使用

RUN --security=insecure

RUN --security=sandbox

CMD

dockerfile中只能有一个cmd生效(最后一个)

cmd主要目的是为执行容器提供默认值,这些默认值可以包含可执行文件,也可以省略。省略是必须制定ENTRYPOINT值。

cmd在构建时不执行任何内容,但为镜像指定预期的命令。

cmd使用[]的时候,如果第一行的参数在指定位置或系统环境变量中找不到,就会被当作entrypoint参数使用

如果使用 CMD 为 ENTRYPOINT 指令提供默认参数,则应使用 JSON 数组格式指定 CMD 和 ENTRYPOINT 指令。

三种格式

  • CMD ["executable","param1","param2"] exec格式,首选
  • CMD ["param1","param2"] 作为entrypoint的默认参数
  • CMD command param1 param2  shell格式

exec格式不回调用shell命令,因此不会发生正常的shell处理。

CMD [ "echo", "$HOME" ]  就不会对$HOME进行处理

如果需要shell处理,要么使用shell格式,要么直接执行shell,例如CMD [ "sh", "-c", "echo $HOME" ]

使用exec格式并执行shell的时候,是shell在执行环境进行变量拓展,而不是在docker

使用shell格式,命令将直接在/bin/sh中执行

docker run test /bin/bash 会覆盖指定的cmd

LABEL 

将元数据添加到镜像中,value使用双引号,单引号不会解析变量值

镜像默认继承base images的标签,但如果重复,就近应用最近的标签覆盖

docker image inspect --format=‘imagename’ 检查标签

LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

MAINTAINER name

容器作者,已废弃的指令

EXPOSE

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

EXPOSE 80/udp

EXPOSE用于通知docker容器运行时监听的端口,可以指定端口是tcp或udp,默认tcp

暴露端口实际上并不映射端口,只是先指定容器提供服务要用到的端口

docker run时使用-p映射端口,把暴露出的端口和某个宿主机端口建立映射关系

docker run -P,自动映射,将所有暴露的端口随机映射到宿主机的高阶端口

如果tcp和udp的端口都需要暴露。请使用:

EXPOSE 80/tcp
EXPOSE 80/udp

无论expose如何设置,都可以在运行时使用-p标志重写

 docker run -p 80:80/tcp -p 80:80/udp ...

使用docker inspect name 查看容器元数据的ports可以查看端口映射情况

ENV

ENV <key>=<value> ...

设置环境变量,将可用于后续所有指令中。可以通过引号和反斜杠在value中包含空格;等号也可以省略

docker允许同时给env设置多个key value

MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy

ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
    MY_CAT=fluffy

可以通过docker run --env 修改key value

子阶段会继承父阶段或任何祖先阶段的env设置的环境变量

ADD

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

add指令用于复制文件。目录,或url到路径中。(目录本身不会被复制,只复制内容)

src可以指定多个资源;src远程资源的默认全显示600;src的资源如果是可识别的压缩格式,会自动解压缩(tar -x相同行为)

如果远程文件需要身份验证,推荐wget等工具,add并不支持身份验证

dest是一个绝对路径,或相对于workdir的路径

--chown仅适用于构建linux容器的dockerfile,windows不生效

所有新文件的和目录的uid 和gid都是0,除非可选的--chown中指定,如果容器中没有 /etc/passwd 或 /etc/group 文件,并且在 --chown 标志中使用了用户名或组名,则构建将在 ADD 操作上失败


ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/

ADD --checksum=<checksum> <http src> <dest>

进行远程文件校验,目前只支持http源

ADD --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3\
cafd48dd869a9b2945d1036d1dc68d \
https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz /

COPY

从构建上下文复制文件到镜像里

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


COPY --chown=55:mygroup files* /somedir/
COPY --chown=bin files* /somedir/
COPY --chown=1 files* /somedir/
COPY --chown=10:11 files* /somedir/

COPY 接受参数 --from=<name>,将位置设置为以前的构建阶段(FROM   AS <name>),而不是用户发送的构建上下文。如果找不到具有指定名称的构建阶段,会尝试改用具有相同名称的镜像

如果是目录,会复制目录中全部内容,包括文件系统元数据

copy --link 

add --link

dockerfile:1.4+新语法

VOLUME

指定一个匿名卷,但不将匿名卷绑定到宿主机。生成的镜像中如果指定了volume,在run容器的时候,docker会在安装目录下的指定目录里生成一个目录绑定容器的匿名卷。

容器被删除后。保留主机上的文件不会被删除

如果docker run的时候指定了-v ,位置不同会被覆盖。(volume就是为了防止用户docker run -v主机目录:容器目录 时忘记-v指令导致的问题)

USER 

设置用户名uid和可选的用户组gid

user必须是已经建立好的用户,只负责切换

使用user指定用户后,dockerfile中后续的run cmd enrtypoint都将使用该用户

可以使用docker run -u指定用户(会覆盖)

USER <user>[:<group>]

USER <UID>[:<GID>]

USER abc

docker run -i -t -u 1001 busybox sh

WORKDIR

为dockerfile中的任何run cmd rntrypoint copy add设置工作目录

workdir多次使用,如果之后提供的是相对路径,则最终路径是相对于上一个workdir的路径

workdir可以解析以前设置的env环境变量

不指定workdir,默认工作目录为根目录。如果不是从头开始构建镜像,workdir可能是base images设置的,为了避免在未知目录进行意外操作,建议最好明确设置workdir 

ONBUILD 触发器

为镜像添加一个触发器指令,当该镜像作为其他镜像的base image时,将会执行onbuild指令。就像是在下游的cockerfile中的from指令后立即插入的新指令。

ENTRYPOINT

Dockerfile(9) - ENTRYPOINT 指令详解 - 腾讯云开发者社区-腾讯云

HEALTHCHECK

Dockerfile(12) - HEALTHCHECK 指令详解 - 腾讯云开发者社区-腾讯云

STOPSIGNAL

参考: https://cloud.tencent.com/developer/article/1896355​​​​​​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值