Dockerfile
Dockerfile
FROM:
基于哪个镜像上层做新的镜像
第一行要求为FROM <image>:<tag>
LABEL: 让用户为镜像指定各种各样的元数据(docker新版本所支持)
MAINTAINER: 相同功能,1.8版本前都支持
Syntax: LABEL <key>=<value> <key>=<value> <key>=<value>
COPY: 将宿主机中文件打包提供(复制)到目标镜像中
Syntax: COPY <src>...<dest>或
COPY ["<src>"...."<dest>"]
dest: 生成目标目录的路径
src: 要复制的源文件或目录,支持使用通配符,建议使用绝对路径,否则,COPY指定则以WORKDIR为起始路径
注意:
<src>必须是build上下文中的路径,不能是其父目录中的文件
如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制
如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以"/"结尾
如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径
例:
~]# mkdir /app/docker
~]# vim Dockerfile
FROM busybox:latest
MAINTAINER "Fangwenkai"
COPY ["index.html","/data/web/html/"] // 复制单个文件到景象中/data/web/html中保留
COPY ["yum.repos.d","/etc/yum.repos.d/"] // 复制本地yum.repos.d下的所有文件到新镜像中保留,因为src为目录,所以dest要以/结尾
~]# docker build -t httpd:latest ./ // 构建
~]# docker images
httpd latest 502b9f32b549 10 minutes ago 1.21MB
ADD: 类似于COPY命令,ADD支持使用TAR文件和URL路径
Syntax: ADD <src>..<dest>或
ADD ["<src>"..."<dest>"]
注意:
同COPY指令
如果<src>为URL且<dest>不以"/"结尾,则<src>指定的文件将被下载并直接创建为<dest>;如果<dest>以"/"结尾,则文件名URL指定的文件将直接下载并保存为<dest>/<filename>
如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似与"tar -x"命令;然后,通过URL获取到的tar文件将不会自动展开
如果<src>有多个,或其间接使用了通配符,则<dest>必须是一个以"/"结尾的目录路径;如果<dest>不以"/"结尾,则其被视作一个普通文件,<src>的内容将本直接写入到<dest>
例:
ADD ["http://nginx.org/download/nginx-1.17.0.tar.gz","/usr/local/src/"] // 即使dest不存在也会自动创建,src为URL光下载不解压 ADD ["nginx-1.17.0.tar.gz","/usr/local/src/nginx/"] // 会将压缩包展开放在指定目录中
WORKDIR: 用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
Syntax: WORKDIR <dirpath>
在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径
另外,WORKDIR也可调用由ENV指定定义的变量
例如:
WORKDIR /var/log
WORKDIR $STATEPATH
例:
WORKDIR /usr/local/src ADD ["nginx-1.17.0.tar.gz","./"] // 此时的当前目录变为/usr/local/src
VOLUME: 用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷
Syntax: VOLUME<mountpoint>或
VOLUME["<mountpoint>"]
如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
例:
VOLUME /data/mysql/ // 在容器中挂载指定目录/data/mysql,对应本地则随机位置
EXPOSE: 用于为容器打开指定要监听的端口以实现外部通信
Syntax: EXPOSE <port>[/protocol][<port>[/protocol]...]
protocol用于指定传输层协议,可为tcp或udp二者之一,默认为tcp协议
EXPOSE指令可一次指定多个多口,例如
EXPOSE 11211/udp 11211/tcp
例:
EXPOSE 80/tcp // 指定容器内打开的端口 ~]# docker run --name h4 --rm -P httpd:v0.1-6 /bin/httpd -f -h /data/web/html // 添加"-P"即可在宿主机暴露随机端口
ENV: 用于为镜像定义所需要的环境变量,并可被Dockerfile文件中位于其后的其他指令(如ENV、ADD、COPY等)所调用
调用格式为$variable_name或${variable_name}
Syntax:
ENV <key> <value>或
ENV <key>=<value>...
第一种格式中,<key>之后的所有内容均会被视作其<value>的组成部分,因此,一次只能设置一个变量
第二种格式可以用一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<value>中包含空格,可以以反斜线(\)进行转移,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行
定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
例:
ENV DOC_ROOT=/data/web/html/ \ WEB_SERVER_PACKAGE=nginx-1.17.0.tar.gz COPY ["index.html","$DOC_ROOT:-/data/web/html/"] // $DOC_ROOT:-/data/web/html(当$DOC_ROOT没有值时则使用-后面的值) ADD ["$WEB_SERVER_PACKAGE","./"] ~]# docker run --name h5 --rm -P -e WEB_SERVER_PACKAGE=nginx-1.17.1.tar.gz httpd:v0.1-7 printenv -e: 修改env全局环境变量
RUN: 用于指定docker build过程中运行的程序,其可以是任何命令
Syntax:
RUN <command>或
RUN ["<executable>","<paraml>","<param2>"]
第一种格式中,<command>通常是一个shell命令,且以"/bin/sh -c"来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号;
第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式
RUN ["/bin/bash","-c","<executable>","<paraml>"]
例:
FROM busybox:latest MAINTAINER "Fangwenkai" ENV DOC_ROOT=/data/web/html/ \ WEB_SERVER_PACKAGE=nginx-1.17.0.tar.gz COPY ["index.html","$DOC_ROOT:-/data/web/html/"] COPY ["yum.repos.d","/etc/yum.repos.d/"] ADD ["http://nginx.org/download/$WEB_SERVER_PACKAGE","/usr/local/src/"] WORKDIR /usr/local/src #ADD ["$WEB_SERVER_PACKAGE","./"] VOLUME /data/mysql/ EXPOSE 80/tcp RUN cd /usr/local/src && \ // 在build过程中进入到指定目录并解压nginx-1.17.0.tar.gz tar -xf $WEB_SERVER_PACKAGE
CMD: 类似与RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
RUN指令运行于映像文件构建过程中,而CMD指令云星宇基于Dockerfile构建出的新映像文件启动一个容器时
CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
Syntax:
CMD <command>或
CMD ["<executable>","<param1>","<param2>"]或
CMD ["<param1>","<param2>"]
前两种语法格式的意义同RUN
第三种则用于为ENTRYPOINT指令提供默认参数
ENTRYPOINT: 类似CMD指令的功能,用于为容器指定默认执行程序,从而使得容器像是一个单独的可执行程序
与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当做参数传递给ENTRYPOINT指定的程序
不过,docker run命令的--entrypoint选项的参数可覆盖ENTEYPOINT指令所指定的程序
Syntax:
ENTRYPOINT <command>
ENTRYPOINT ["<executable>","<param1>","<param2>"]
docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后作为其参数使用
Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个生效
USER: 用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID;默认情况下,container的运行身份为root用户
Syntax:
USER <UID>|<USERNAME>
需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败
HEALTHCHECK: 容器健康状况检查命令
Syntax:
HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE
第一个的功能是在容器内部运行一个命令来检查容器的健康状况
第二个的功能是在基础镜像中取消健康检查命令
[OPTIONS]:
--interval=DURATION(default:30s) // 两次检查默认的时间间隔为30s
--timeout=DURATION(defaul:30s) // 健康检查命令运行超时时长,默认为30s
--start-period=DURATION(default:0s) // 当容器启动多长时间后运行健康检查,默认不等待
--retries=N(default:3) // 检查几次
注意:
HEALTHCHECK命令只能只能出现一次,如果出现了多次,只有最后一个生效
CMD后边的命令的返回值决定了本次健康检查是否成功,返回值如下
0: success - 表示容器是健康的
1: unhealth - 表示容器已经不能工作了
2: reserved - 保留值
例:
HEALTHCHECK --interval=5s --timeout=3s --start-period=5s \ CMD wget -O - -q $HOSTNAME || exit 1
SHELL: 允许覆盖用于shell形式的命令的默认shell,Linux上的默认shell是/bin/sh -c,而在windows上为cmd /s /c
Syntax:
SHELL ["executable","parameters"]
SHELL指令必须以JSON格式写入Dockerfile
SHELL指令可以多次出现,每条SHELL指令都会覆盖所有先前的SHELL指令,并影响所有后续指令
ARG: 设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<value>来指定参数
如果用户在build镜像时指定了一个参数没有定义在Dockerfile中,那么将有一个Warning
例:
ARG author="xiaofang" // 定义变量所有者为"xiaofang" LABEL maintainer="${author}" // 调用author变量,最后inspect会查看到所有者为"xiaofang"
ONBUILD:
用于在Dockerfile中定义一个触发器
Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件
在后面的这个Dockefile中的FROM指令在build过程中被执行时,将会"触发"创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器
Syntax:
ONBUILD <INSTRUCTION>
尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuil
在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指顶的源文件时会失败
例:
~]# vim /docker/image3/Dockerfile .... ONBUILD ADD http://nginx.org/download/nginx-1.16.0.tar.gz /usr/local/src/ .... image3]# docker build ./ -t myweb:v0.3-10 image3]# mkdir ../image4/; cd ../image4 image4]# vim Dockerfile FROM myweb:v0.3-10 // 引用刚刚带有ONBUILD构建的镜像 RUN mkdir /test // 创建/test目录 image4]# docker build ./ -t test:v0.1-onbuild // 执行后会发现这个镜像会下载上一个Dockerfile中ONBUILD后的URL