Dockerfile的作用
相当于docker构建镜像的说明书,docker会根据Dockerfile中的构建命令一步一步的构建镜像,每一步构建指令都会产生一个镜像,在这个镜像的基础上在执行下一步构建指令,本博客不会涉及docker构建镜像的细节,只会介绍Dockerfile中的命令,运行dokcer build命令可以构建镜像,此时会将工作目录下的所有文件发送给docker守护进程(不管构建过程是不是需要)
Parser directives
Parser directives会影响docker后续处理行的方式,它不会在构建中填加额外的层,关于构建过程中层的概念,请查看:docker 的image是什么
使用格式:#directive=value
注意事项:以下使用方式会导致Parser directives无效
换行
# direc \tive=value
重复定义
# directive=value1# directive=value2FROM ImageName
出现在构建命令之后
FROM ImageName# directive=value
出现在非parser directive之后
# About my dockerfile# directive=valueFROM ImageName
不是合法的parser directive,目前docker支持的Parser directives只有escape,所以我在这里废话总结
# unknowndirective=value# knowndirective=value
escape
定义转义符号,目前支持两种形式
# escape=\ (backslash)
# escape=` (backtick)
如果在dockerfile中未指定,则默认为\,这会导致一些麻烦,因为\是windows的文件路径分割符,如果我们如下使用:
FROM microsoft/nanoserverCOPY testfile.txt c:\\RUN dir c:\
二、三行命令会被翻译成:
COPY testfile.txt c:\RUN dir c:
因此在windows上最好使用 ` 号
ENV
dockerfile中可以使用环境变量:$variable_name或是${variable_name},这两种格式被同等对待,但是括号可以处理空格的状态,
${variable_name}具有更多的用法:
${variable:-word}:如果variable值没有被指定,那么将使用word作为值
${variable:+word}:如果variable值被指定,那variable最终的值将是word,如果没有被指定,则默认为空字符串
环境变量也会被转义字符转义:
COPY \$foo /quux 等效于 COPY $foo /quux
环境变量的值可以通过ENV指令指定,ENV定义的值只有在ENV命令外才会生效,例如:
ENV abc=hello
ENV abc=bye def=$abcENV ghi=$abc
def的值将是hello(由于abc=hello在第一条ENV命令中,位于第二条ENV命令的def外),ghi的值将是bye
.dockerignore文件
前面说过docker build指令会将工作目录的所有文件发送给docker守护进程,在此之前,docker会检查工作目录下是否存在.dockerignore文件,通过.dockerignore文件,我们可以指定哪些文件不用发送给docker守护进程,.dockerignore文件以一行为单位,表示哪些文件不需要添加到docker守护进程,.dockerignore中的文件路径都是相对于工作目录而言,如果我们在一行的前面标记#,则改行被当作注释:
# comment*/temp*
*/*/temp*temp?
上述文件每行意义如下:
.dockerignore也支持通配符,**表示匹配任意数目的目录,!表示排除在外的意思,例如:
dockerignore也支持通配符,**表示匹配任意数目的目录,!表示排除在外的意思,例如:
*.md!README.md
除了README.md以外的所有.md文件都会被排除在外,.dorckerignore文件的最后一行具有最高的优先级,它会覆盖之前的匹配,例如:
*.md
!README*.md
README-secret.md
即使README-secret.md匹配!README*.md,由于README-secret.md在最后一行,因此仍然会将README—secret.md移除,再如:
*.md
README-secret.md
!README*.md
README-secret.md不会被移除,因为!README*.md在最后一行
docker一定会见工作目录的Dockerfile文件发完docker守护进程,即使在.dockeringnore中声明Dockerfile
FROM
FROM指令具有三种格式:
FROM
FROM
FROM
要点:
FROM为接下来的构建指令指定基础镜像,一个有效的Dockerfile文件必须以FROM指令开头
除arg指令以外的构建指令都不能出现在FROM之前,Dockerfile文件可以出现多个FROM指令,此时一个Dockerfile可以构建多个image,并且输出这些image的ID,在执行FROM指令时,之前构建命令生成的状态会被清空,若arg指令位于FROM之外,FROM内部的指令不能引用arg,如果想使用,必须声明一遍:
ARG VERSION=latest
FROM busybox:$VERSION#声明过后,才能替换RUN指令为的$VERSION为latestARG VERSION
RUN echo $VERSION > image_version
FROM指令允许添加镜像的别名(指令中的[AS
tag与digest指镜像的版本信息,如果不指定,则默认为latest
RUN
RUN指令有两种形式:
#shell形式,命令会运行在shell脚本上,在linux上默认为/bin/sh -c,在windwos上默认为cmd /S /CRUN
要点:
RUN指令会在当前镜像的基础上执行命令
如果当前镜像不支持默认的shell,可以使用第二种形式,exec形式会解析成JSON数组,所以不能使用单引号
RUN ["/bin/bash", "-c", "echo hello"]
可以通过SHELL指令更改默认的shell环境
exec形式不会默认调用shell,类似于RUN [ "echo", "$HOME" ]的指令(需要环境变量解析)将不会得到解析,环境变量解析的工作由shell进行,不是docker
RUN命令的执行结果会进行缓存,以便加快二次构建的速度,可以使用docker build --no-cache,禁止使用缓存
CMD指令具有三种形式
#exec形式,推荐使用CMD ["executable","param1","param2"]#作为ENTRYPOINT指令的参数CMD ["param1","param2"]#shell形式CMD command param1 param2
要点:
dockerfile中只有一条CMD指令会生效,如果有多条,只有最后一条CMD指令生效
CMD指令主要为ENTRYPOINT提供默认值,此时CMD指令与ENTRYPOINT指令都必须使用exec格式
exec指令会解析成JSON格式,因此必须使用双引号
exec形式不会调用shell,这意味着CMD [ "echo", "$HOME" ]不会进行环境变量解析,如果想要使用,更改为CMD [ "sh", "-c", "echo $HOME" ],环境变量的解析均有shell负责,而不是docker
当镜像运行时才会运行CMD指令,而RUN是在构建阶段运行
如果使用shell形式,命令会运行在/bin/sh -c上
如果不想运行在shell上,就使用exec形式,但是要指明可执行文件的位置
如果在docker run命令上添加了参数,会覆盖CMD中对应的默认值
LABEL
LABEL
要点:
LABEL命令增加元数据到image中(描述作用)
LABEL命令使用key-value模式
子image会继承父image的LABEL,同时可以覆盖其中的值
可以使用docker inspect命令查看Labels
MAINTAINER
MAINTAINER
要点:
指定image的创作者
EXPOSE
EXPOSE
要点:
EXPOSE让container在运行时监听特定的端口,可以指定端口运行tcp或是udp命令,默认情况下为tcp
EXPOSE 80/udp
EXPOSE命令不会真正发布端口,只是image构建者告诉container运行者应该如何映射端口
docker run指令的-p参数可以指定端口映射,以及对应的协议,此时才会发布端口
docker run -p 80:80/tcp -p 80:80/udp ...
ENV
#一行只能设置一个全局变量,双引号会被去除ENV
要点:
ENV指令设置的key-value相当于全局变量
ENV指令设置的全局变量会持久化,可以使用docker inspect查看,可以使用docker run --env
ADD
ADD [--chown=
要点:
[--chown=
ADD指令将文件、文件夹、URL处的文件(夹)拷贝到
如果
ADD hom* /mydir/ # adds all files starting with "hom"ADD hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
.
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # adds "test" to /absoluteDir/
除非指定了--chown,否则所有新创建的文件以及目录的UID与GID均为0,--chown允许UID以及GID为数字或是字符串,也可以是两者的组合,/etc/passwd和/etc/group文件会被用来将字符串转换为对应的数字形式的UID以及GID,如果只指定了UID,GID默认取UID的值
如果URL需要验证登陆,ADD指令需要与RUN wget、RUN curl指令搭配使用(提供账号密码)
如果使用STDIN给出Dockerfile,可能会没有上下文,此时ADD指令只能通过URL获取资源
#没有上下文docker build -< Dockerfile#解压后的文件作文上下文docker build - < archive.tar.gz
如果
如果
如果
如果
将多个文件或是文件夹ADD到
如果
COPY
copy有两种形式:
COPY [--chown=
要点:
copy将文件从
copy指令可以使用--from=
ENTRYPOINT
ENTRYPOINT具有两种写法:
#exec形式ENTRYPOINT ["executable", "param1", "param2"]#shell形式ENTRYPOINT command param1 param2
要点:
运行docker run指令后会运行的指令
docker run指令后面的参数或是命令会附加到ENTRYPOINT上,会覆盖cmd对应的值,例如cmd指令指定了-name的值,如果使用docker run -name....,则容器最终的name为docker run指定的值
通过docker run --entrypoint会替换ENTRYPOINT的值
shell形式不接受cmd指定的参数,shell形式有一个缺点,就是启动的可执行程序不会接收信号,如果我们运行docker stop指令,可执行程序将不会接收到停止信号
如果定义了多条entrypoint指令,只有最后一条可以生效
cmd指令与ENTRYPOINT指令的关系
两者均制定了容器运行时执行的命令
Dockerfile应该至少指定CMD或是ENTRYPOINT中的一个
CMD可以为ENTRYPOINT指定参数值
CMD指定的值可以被命令中对应的参数值替换,两者的协作效果如下
VOLUME
命令格式:
#定义匿名数据卷VOLUME ["/data"]
要点:
VOLUME指令用于创建一个挂载点,挂载点用于存储持久化数据,一般不建议将数据存储在Docker容器的可写层(原因我还没看),挂载点可以理解为就是一个用于存储数据的文件,只是这个文件由docker统一管理,当然,也可以将本地文件映射成挂载点,此时数据将写入到本地文件中
volume分为两种,一种是匿名卷,一种是实名卷,匿名数据卷就是未映射到本文将的卷,一般存储在/var/lib/docker/volumes中,当容器被删除时,对应的卷也会被删除,实名卷映射到了本地文件,当容器被删除时也不会被删除
实名卷只可以通过docker run -v指定,例如docker run -v /var/temp:/app
docker run指令会保留作为卷的文件之前的数据,例如:
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
/myvol中将存在greeting文件,并且该文件保留hello world的字符
在windows上使用卷时,挂载文件必须存储在空文件夹或是一开始不存在的文件夹下,并且文件夹不能存储在C盘
使用实名卷需要注意,实名卷可能会影响容器的移植性,因为实名卷对应的文件结构受操作系统的影响,因此,我们不能在Dockerfile中指定使用实名卷(影响移植性),只能通过docker run -v指令
USER
格式:
USER
要点:
用于指定运行image、RUN、CMD、ENTRYPOINT的user和group,只有对应的user以及group可以运行image
如果user没有对应的group,则默认使用root
WORKDIR
命令格式:
WORKDIR /path/to/workdir
要点:
RUN、CMD、ENTRYPOINT、COPY、ADD指令可以使用,当这些指令未指出工作目录时,则默认使用WORKDIR指定的目录作为工作目录
如果WORKDIR指定的目录不存在,则会默认创建
WORKDIR指令可以使用多次,如果使用相对路径,会承接到之前的WORKDIR指定的路径中,例如:
WORKDIR /aWORKDIR bWORKDIR cRUN pwdRUN指令指定的文件为 /a/b/c/pwd
WORKDIR指令可以使用ENV指定的环境变量,例如:
ENV DIRPATH /path
WORKDIR $DIRPATH/b
RUN pwdRUN指令指定的文件为/path/b/pwd
ARG
命令格式:
ARG
要点:
ARG定义参数的值必须通过docker build --build-arg
dockerfile文件可以使用多个ARG参数
FROM busybox
ARG user1
ARG buildno
...
一般不建议将账号密码等敏感信息作为ARG参数的值,因为可以通过docker history命令查看到
ARG指令可以指定参数的默认值
ARG指令只对位于自己下方的指令有效,镜像构建完毕后就会失效,如果想在多个镜像的构建过程中使用,则在多个镜像的构建过程中指定相同的ARG:
FROM busybox
ARG SETTINGS
RUN ./run/setup $SETTINGS
FROM busybox
ARG SETTINGS
RUN ./run/other $SETTINGS
ENV指令会覆盖ARG指令中相应的参数,例如:
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 .
CONT_IMG_VER的值将是v1.0.0
有些ARG参数是预定义的:
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
可以直接使用,这些参数的值不会被docker history输出,我们也可以自己覆盖这些参数
如果指定的ARG指令与之前构建阶段的不同,如果在其他指令中使用过ARG,则会出现缓存缺失,但如果它的值杯ENV指令覆盖,则不会出现:
1 FROM ubuntu2 ARG CONT_IMG_VER3 ENV CONT_IMG_VER hello4 RUN echo $CONT_IMG_VER
因为ARG指令的CONT_IMG_VER杯ENV覆盖了,所以不会出现缓存确实
ONBUILD
ONBUILD [INSTRUCTION]
要点:
指定运行镜像后紧接着执行的命令
这个指令是如何起作用的呢?在构建镜像时,builder会将ONBUILD指令的值添加到镜像的OnBuild中,可以通过运行docker inspect查看,当其他镜像使用这个镜像时,builder会查看OnBuild区域,并且按顺序执行它们,OnBuild区域的值不会被继承
STOPSIGNAL
STOPSIGNAL signal
要点:
使用这个指令允许用户自定义应用在收到 docker stop 时所发送的信号
HEALTHCHECK
#通过运行容器中的指令来判断容器是否健康,CMD可以是shell或是exec形式HEALTHCHECK [OPTIONS] CMD command#禁止所有父镜像的健康检查HEALTHCHECK NONE
要点:
这条指令用于检查容器的健康状况
如果容器指定了健康检查,会添加额外的health字段,这个字段一开始是starting,当健康检查通过以后,会更改为healthy,如果几次尝试都失败,则会设置为unhealthy
OPTIONS字段
#两次健康检查的间隔--interval=DURATION(默认为30s)健康检查命令运行超时时间,如果超过这个时间,本次健康检查视为失败--timeout=DURATION(默认为30s)#应用启动的初始化时间,在启动过程中的健康检查失效不会计入--start--period=DURATION(默认为0s)#当连续失败指定次数后,则将容器状态视为unhealthy--retries=N(默认为3次)
如果有多条HEALTHCHECK,只有最后一条才会起作用
这条命令执行完毕后,会输出一个数字:
#成功0:success#失败1:unhealthy#保留字段,没有意义2:reserved
SHELL
SHELL ["executable", "parameters"]
要点:
用于指定shell形式的命令运行的shell环境,linux默认的shell环境为["/bin/sh","-c"],windwos默认为
["cmd","/S","/C"]
END
碧茂课堂精彩课程推荐:
1.Cloudera数据分析课;
2.Spark和Hadoop开发员培训;
3.大数据机器学习之推荐系统;
4.Python数据分析与机器学习实战;
详情请关注我们公众号:碧茂大数据-课程产品-碧茂课堂
现在注册互动得海量学币,大量精品课程免费送!