Dockerfile功能以及其工作流程
docker可以通过自动阅读dockerfile文件建立镜像,dockerfile是一个文本文档型的,所有用户能在命令行进行的操作命令都可以在此定义,从而将这些命令组合起来,并生成一个直接可用的镜像。使用“docker build”,用户可以连续执行多个指令,从而实现构建的自动化。本文将会介绍在dockerfile中可以执行的命令参数。
docker build命令可以从一个dockerfile或者一个文本构建镜像,构建文本可以是一个本地路径或者是一个GIT的URL路径。"docker build ."表示使用当前目录作为上下文进行构建(警告,不要在根目录执行此命令,这将会把你的硬盘的上下文信息全部传送到docker进程当中,自己想想后果吧),默认情况下,如果不使用-f选项指定,会加载名为Dockerfiler的文件。然后可以使用-t选项指定构建镜像的tag标签以及仓库名称,例如(可以添加多个参数):
docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
docker的构建操作是由docker守护进程完成的,而非CLI(命令行操作)。其构建顺序是,首先把上下文信息发送到进程,然后docker守护进程将会依次执行Dockerfile里面的指令到新的镜像当中,并且会在结束后自动清除上下文信息。为了提升Docker性能,还可以在上下文目录添加一个".dockerignore"文件。需要注意的是,Dockerfile中的每一条指令都是完全独立的,也就是说你不能指望通过"RUN cd /tmp"指令,将下一条指令的工作环境设置到"/tmp"目录下面。
docker会尽量使用镜像缓存(默认),从而提高其工作性能。当然,也可以通过"--no-cache=true"不使用缓存构建。构建完成后,就可以通过push指令上传到指定注册中心的仓库了。
Dockerfile写作风格:
一,基本语法
# Comment
INSTRUCTION arguments
"INSTRUCTION"是不区分大小写的,但是为了区分起见,以大写为好。Dockerfile每一行仅支持一条指令,Dockerfile的起始位置的第一个非注释行需要使用"FROM"指令指定构建使用的来源镜像,指令区域的起始最好有以"#"的注释行,以说明当前区域执行的任务内容。
二,变量置换
- 在dockerfile中,变量声明可以表示为$variable_name或者${variable_name},主要是用来区别没有空格的变量,例如${foo}_bar。
- dockerfile中的变量声明也支持少量的bash修饰符,例如:
- ${variable_name:+word}: 如果已经赋值且非空,则使用$variable_name的值,如果没有,则返回空字符串
- ${variable_name:-word}: 如果已经赋值,则使用$variable_name的值,如果没有,使用word
- word可以为任意字符串,包含附加的环境变量
- 也可以使用"\"符号进行转义,例如"\$foo"表示内容就是"$foo"
- 环境变量可以在以下指令中使用:
- ADD|COPY|ENV|EXPOSE|LABEL|USER|WORKDIR|VOLUME|STOPSIGNAL
- 也可以使用ONBUILD指令(需要docker版本大于1.4)
- 环境变量支持替换
三,dockerignore file
在docker执行命令(发送上下文信息到进程之前)时,如果存在".dockerignore"文件,则其中定义的文件或目录不ADD或COPY指令添加到镜像当中。例如:
*/temp* #如,/aa/template.txt
*/*/temp* #如,/aa/bb/template.conf
temp? #如,/tempaa或/tempbb
*.md
!README.md #取反,这两行结合使用,表示包含所有以.md结尾的,除了README.md以外的文件
使用匹配格式都参照go语言风格
Dockerfile指令说明:
- FROM
- 作用:指令构建来源镜像,它必须处于第一个非注释指令
- 语法:FROM <image> 或者 FROM <image>:<tag> 或者 FROM <image>@<digest>,后两个(标签和摘要)是可选的,如果无法匹配,则返回错误
- MAINTAINER
- 作用:指定生成镜像的作者
- 语法:MAINTAIN <name>
- RUN
- 作用:在引用的的镜像中执行命令,交提交结果,用于dockerfile后面的操作
- 语法:RUN有两种写法
- RUN <command>
- RUN ["executable", "param1", "param2"]
- 样例:
- RUN /bin/bash -c "source $HOME/.bashrc ; echo $HOME" #跨行操作时可以添加反斜杠
- RUN ["/bin/bash", "-c", "echo hello"]
- 注意事项:
- RUN指令的部分操作会存储在缓存当中,如果下次构建不使用"--no-cache=true",则有可能会出问题
- CMD
- 作用:CMD的主要目的是为执行容器提供一些默认参数,这些设置可以包括一个可执行文件,或者一个系统命令。CMD指令只能在dockerfile中存在一次,如果有多条,则只执行最后一条
- 语法:CMD有三种写法
- CMD ["executable", "param1", "param2"]
- CMD ["param1", "param2"] #此种写法需要配置ENTRYPOINT指令结合使用,如果两个都独立使用,则只会执行最后一个CMD或者ENTRYPOINT指令
- CMD command param1 param2 #shell风格
- LABEL
- 作用:LABEL指令用来添加一些元数据到镜像当中,LABEL是键值对类型数据,一个镜像可以有一个或者多个标签,但是过多的标签则会导致生成一个低能的镜像。当指定多个标签时,尽量在一层显示,而不是使用多个LABEL指令指定。可以使用docker inspect查看镜像的LABEL信息
- 语法:LABEL <key>=<value> <key>=<value> <key>=<value> <key>=<value> ……
- EXPOSE
- 作用:指定容器映射到主机的端口,Docker容器的IP是随机生成的,所以外部访问是需要通过主机端口映射访问的,而EXPOSE指定了其映射到主机的端口,具体可参考man docker-run中的-p或者-P选项
- 语法:EXPOSE <port> [<port>...]
- ENV
- 作用:设置环境变量,此处的变量可以在dockerfile中引用
- 语法:ENV有两种写法
- ENV <key> <value>
- ENV <key>=<value> .... #建议用此种写法,只产生一个ENV缓存层
- ADD
- 作用:ADD指令可以将源(可以是文件,目录或者URL)添加到容器里面的路径下,可以使用匹配规则添加文件。如果是个URL,则会将其下载到容器目标路径当中
- 语法:ADD有两种写法
- ADD <src> ... <dest>
- ADD ["<src>",... <dest>] #这种形式一般用于包含空格的路径
- COPY
- 作用:COPY是将源文件或目录复制到容器内指定路径内,如果不携带dest参数,则会创建完整的缺失目录
- 语法:COPY有两种写法
- COPY <src> ... <dest>
- COPY ["<src>",... <dest>] #这种形式一般用于包含空格的路径
- ENTRYPOINT
- 作用:该指令的使用分为两种情况,一种是自己单独使用,另一种是和CMD结合使用。结合使用时,ENTRYPOINT指令只能执行命令,但不能指定参数部分;CMD指令不是一个完整的可执行命令,而仅仅是参数部分。例如以下案例:
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
- 语法:ENTRYPOINT同样有两种语法
- ENTRYPOINT ["executable", "param1", "param2"]
- ENTRYPOINT command param1 param2
- VOLUME
- 作用:VOLUME指令可以创建一个挂载点给容器使用,从而实现容器内数据的持久化(容器在关闭后数据是会消失的)。卷可以通过docker create 来创建,也可以直接使用docker run创建,卷只能在没有容器连接时才能被删除,通过docker run 创建的卷是可以共享给其它容器使用的。例如(有关volume更多介绍,请参考链接:https://docs.docker.com/engine/userguide/containers/dockervolumes/#mount-a-host-directory-as-a-data-volume):
- docker run -d -P --volume-driver=flocker -v my-named-volume:/opt/webapp --name web training/webapp python app.py
- 作用:VOLUME指令可以创建一个挂载点给容器使用,从而实现容器内数据的持久化(容器在关闭后数据是会消失的)。卷可以通过docker create 来创建,也可以直接使用docker run创建,卷只能在没有容器连接时才能被删除,通过docker run 创建的卷是可以共享给其它容器使用的。例如(有关volume更多介绍,请参考链接:https://docs.docker.com/engine/userguide/containers/dockervolumes/#mount-a-host-directory-as-a-data-volume):
-
- 语法:VOLUME [‘/data‘]
- USER
- 作用:用以指定用户名或者UID,当使用RUN、CMD和ENTRYPOINT指令的时候,会以此身份进行运行
- 语法:USER daemon
- WORKDIR
- 作用:WORKDIR指令用以设定RUN、CMD和ENTRYPOINT指令的工作目录
- 语法:WORKDIR /path/to/workdir
- ARG
- 作用:ARG指令定义了一个变量,这个变量可以接受docker build --build-arg <argname>=<value>的入参
- 语法:ARG <name>[=<default value>]
- 用例:
- FROM images1
- USER ${user:-some_user}
- ARG user
- USER $user
- docker build --build-arg user=user_name Dockerfile
- ONBUILD
- 作用:ONBUILD指定的指令在构建镜像时并不会执行,只会在构建其子镜像时执行
- 语法:ONBUILD [INSTRUCTION]
- STOPSIGNAL
- 作用:STOPSIGNAL用以设置退出状态码,可以是正常的系统信号,如SIGKILL,也可以是匹配的数字,主机可以通过这个信号关闭容器
- 语法:STOPSIGNAL signal