参考链接 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