Dockerfile指令详解

1. FROM

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

Or

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

Or

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

Form指令,会开始一个新的build阶段,并且为接下来的指令设置基础镜像.因此,一个有效的Dockerfile必须以FROM作为指令的开头.任何有效的镜像都可以当做基础镜像,而且还可以很轻松的从公共仓库拉取公共镜像.

在Dockerfile中,ARG指令是唯一一个可以出现在FROM指令之前的指令.

在一个Dockerfile中,FROM指令可以多次出现,用来构建多个镜像,或者将一个build阶段产生的镜像当做另一次build的依赖.

在每个新的FROM指令之间,会将前面的内容进行提交,并将上一个阶段最后的镜像ID输出.
每个FROM指令,执行时会清除之前指令的执行信息.

为了方便记忆,还可以使用AS name为新构建的镜像起一个名字.
name可以,被用于接下来的FROMCOPY --from=<name|index>指令引用.

tagdigest值也是可选的,如果不使用的话builder会自动为我们的新镜像分配一个latest作为默认tag.

--platform可以用于指定镜像的来源的平台,以防FROM指令引用了一个多平台的镜像,比如linux/amd64, linux/arm64, or windows/amd64等平台.

默认的,执行build命令的目标平台会被当做默认平台.

–platform 的值还可以使用全局参数,比如--platform=$BUILDPLATFORM.

1.1 ARG和FROM

FROM指令支持任何出现在第一个FROM指令之前,被ARG指令声明的变量.
因此CODE_VERSION对于两次FROM都有效.

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

FROM extras:${CODE_VERSION}
CMD  /code/run-extras

在FROM指令之前使用ARG指令声明的变量,处于build阶段之外,因此,这个变量也可以被FROM后的任何指令所使用.

但在build阶段的指令中,如果想要使用在第一个FROM之前声明的ARG变量的值,需要再次使用ARG指令+变量名,有种在build阶段引入此变量的含义.
比如下面第三行,处于build阶段,因此如果不使用
ARG VERSION将其引入build阶段,则在
RUN echo $VERSION > image_version,该变量是unset的空值.

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

2. RUN

RUN指令有2种形式:

1)shell形式:
命令在shell中执行,默认的,如果是在Linux则相当于/bin/sh -c的方式执行命令,而如果是在Windows系统中,则相当于cmd /S /C

RUN <command>

shell形式的默认shell可以通过SEHLL命令来修改.
在shell形式中还可以使用\来当做续行符.比如下面的2个例子是等价的:

RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

2)exec形式:

RUN ["executable", "param1", "param2"] (exec form)

RUN指令会在当前镜像的基础之上,创建一个新的镜像层来执行后面所传递给它的命令,并且提交执行结果,而这个被提交的镜像层会被用来当做Dockerfile中下一个指令的基础镜像.

分层的RUN指令及生成新层级的提交机制,构成了Docker的主要理念,它使得镜像的创建可以非常廉价,而且可以基于镜像历史中的任何一个点创建容器,就像管理source一样.比如Git,我们可以随时切换到任何分支进行操作.

exec 形式,可以避免一些问题:

  1. it possible to avoid shell string munging
    不知道如何能翻译的比较好.举例来说,如果一个脚本test.sh不能自己执行,必须要/bin/sh -c test.sh 的方式来执行,那么,如果使用RUN的shell形式,最后得到的命令相当于:
/bin/sh -c "/bin/sh -c 'test.sh'"

相当于使用了2次/bin/sh,而此时sh进程的id号不是1,因此基于此镜像启动的容器会没有办法接收SIGINAL.

  1. to RUN commands using a base image that does not contain the specified shell executable.
    如果镜像的环境中压根没有/bin/sh,或cmd /S /C,那么使用exec的形式也可以很好的解决.
    比如:只是随便写的,举个例子,csh语法完全不会,这样就可以以cshell来执行命令了.
RUN ["/bin/csh", "-c", "echo hello"]

Note: The exec form is parsed as a JSON array, which means that you must use double-quotes (“) around words not single-quotes (‘).
但是,需要特别注意的是,exec形式,是被当做JSON数组来解析的,所以所有的内容都要用双引号包含起来,重要的事情说三遍.
双引号 双引号 双引号

RUN指令的缓存不会被自动清除,也就是说在下一次build中也会使用缓存,可以使用 --no-cache参数来显示的禁止缓存.
ADD指令也可以是RUN指令的缓存失效.

3. CMD

CMD指令有3种形式:

1)exec形式:(也是推荐使用的形式)

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

2)参数形式:

CMD ["param1","param2"]

param1param2被当做ENTRYPOINT指令的默认参数.

3)shell形式:

CMD command param1 param2

在一个Dockerfile中,只有一个CMD指令能够生效,如果有多个CMD存在,那么只有最后一个CMD指令会生效.

CMD指令的目的是为一个运行中的容器提供一个默认的命令.它可以是一个可执行的命令比如脚本文件a.sh,又或者是不可执行的内容a.txt,但后者必须再指定一个ENTRYPOINT指令.而a.txt将会作为ENTRYPOINT指令的参数.

与RUN命令不同,CMD命令在容器运行阶段才会被执行,而不是镜像编译阶段.

4. LABEL

MAINTAINER指令的替代者,因为LABEL指令更加丰富.

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

LABEL指令,它以键值对的形式,向镜像添加元信息.
如果想要在LABEL的value中使用空格,那么需要使用双引号将内容包含起来:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description=
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值