Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。 一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。 Dockerfile的指令是忽略大小写的,建议使用大写,使用 # 作为注释,每一行只支持一条指令,每条指令可以携带多个参数。 Dockerfile的指令根据作用可以分为两种:构建指令和设置指令。 构建指令用于构建image,其指定的操作不会在运行image的容器上执行; 设置指令用于设置image的属性,其指定的操作将在运行image的容器中执行。 可以在目录下创建.dockerignore文件,让Docker忽略路径下的文件和目录。 DockerFile的每一个指令都会新构建一层。 UnionFS是有最大层数限制的,比如AUFS,曾经是最大不能超过42层,现在是最大不能超过127层。所以,对于一些编译、软件的安装、更新等操作,无需分成好几层来操作,这样会使得镜像非常臃肿,拥有非常多的层,不仅仅增加了构建部署的时间,也很容易出错!! |
指令 | 描述 | 格式 |
from | 构建指令。 指定基础镜像,它是最重要的一个且必须为dokefile文件开篇的第一个非注释行,用于为镜像文件构建过程中指定基础镜像,后续的指令运行于此基准镜像所提供的运行环境 默认,docke会在本机寻找指定的镜像,找不到的时候则从docke hub registery拉取所需镜像,如果会找不到,则报错返回报错信息 如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令。 DockerFile还存在一个特殊的镜像srcatch ,这个镜像是一个虚拟的概念,并不实际存在,它表示一个空白的镜像。 如果你以scratch 作为基础镜像,意味着你将不使用任何镜像为基础,接下来你所写的指令将作为第一层开始存在。不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见。如swarm 、coreos/etcd 。对Linux下静态编译的程序来说,并不需要其他操作提供其运行时支持,所需的一切库都在可执行文件里了,因此使用scratch 作为基础,可以使镜像的体积更加小巧 | from <repository>[:<tag>]或者 from <repository>@<digest> repository为基础镜像名称 tag为镜像标签为可选项,省略时为latest该image的最后修改的版本 |
MAINTAINER | 构建指令 用于为docke提供作者信息,无顺序限制 用于将image的制作者相关的信息写入到image中。当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息。 此命令已经过时,可以使用LABEL maintainer=xxx 来替代,定义多个LABEL时,可以使用 【\】反划线来跨行 | |
copy | 用于从docker主机复制文件至创建的新镜像文件,但不会自动解压,不能从【 远端URL 】 复制。 目标路径是容器内的绝对路径,也可以是工作目录下的相对路径,工作目录可以使用WORKDIR 指令进行指定。 使用COPY 指令会将源路径的文件的所有元数据都拷贝,比如读、写、指定全选、时间变更等。 <源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则 目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录 在使用该指令的时候还可以加上 --chown=<user>:<group> 选项来改变文件的所属用户及所属组。 文件复制准则: | 1 COPY [--chown=<user>:<group>] <源路径>... <目标路径>
2 COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"] |
add | 构建指令 ADD 指令和COPY 的格式和性质基本一致,只不过是在COPY 的基础上增加了一些功能。 如果是一个目录,那么会将该目录下的所有文件添加到container中,不包括目录; 如果<src>是文件且<dest>中不使用斜杠结束,则会将<dest>视为文件,<src>的内容会写入<dest>; 如果<src>是文件且<dest>中使用斜杠结束,则会<src>文件拷贝到<dest>目录下。 目标路径为一个URL时,会将其自动下载到目标路径下,但是其权限被自动设置成了600 ,如果这并不是你想要的权限,那么你还需要额外增加一层RUN 命令进行更改,另外,如果下载的是一个压缩包,同样你还需要额外增加一层RUN 命令进行解压缩。所以,在这种情况下,你还不如指定只用一层RUN ,使用curl 或者wget 工具进行下载,并更改权限,然后进行解压缩,最后清理无用文件! 当你的源路径为压缩文件并且不想让Docker引擎将其自动解压缩,这个时候就不可以使用ADD 命令,你可以使用COPY 命令进行完成 | |
run | 构建指令。 每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行 RUN可以运行任何被基础image支持的命令。如基础image选择了ubuntu,那么软件管理部分只能使用ubuntu的命令 | shell格式RUN <command> 或 exec格式RUN ["executable", "param1", "param2"] 前者将在 shell 终端中运行命令,即 /bin/sh -c ;后者则使用 exec 执行。指定使用其它终端可以通过第二种方式实现,例如 RUN ["/bin/bash", "-c", "echo hello"] 。 |
volume | 设置指令 用于构建镜像时定义匿名卷。 容器存储层应该保持无状态化,容器运行时应尽量保持容器内不发生任何写入操作,对于需要保存动态数据的应用,其数据文件应该将其保存在数据卷中。 容器匿名卷目录指定可以通过docker run 命令中指定-v 参数来进行覆盖。 如果挂载点目录下此前存在文件,docker run命令会在卷挂载完成之后将此前的所有文件复制到新挂载的卷中 运行通过该Dockerfile生成image的容器, /tmp/data 目录中的数据在容器关闭后,里面的数据还存在。 例如另一个容器也有持久化数据的需求,且想使用上面容器共享的 /tmp/data 目录,那么可以运行下面的命令启动一个容器: docker run -t -i - rm -volumes-from container1 image2 bash 其中:container1为第一个容器的ID,image2为第二个容器运行image的名字。 | - VOLUME <路径>
- VOLUME [“<路径1>”, “<路径2>”, …]
|
expose | 设置指令 EXPOSE 指令是声明运行时容器服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。 在Dockerfile中这样声明有两个好处:一个是帮助镜像使用者更好的理解这个镜像服务的守护端口,另一个作用则是在运行时使用随机端口映射时,也就是docker run -p 命令时,会自动随机映射EXPOSE 端口。 要将EXPOSE 和在运行时使用-p <宿主>:<容器端口> 区分开来,-p 是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而EXPOSE 仅仅是声明端口使用什么端口而已,并不会自动在宿主进行端口映射 EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项。 | EXPOSE 端口号 EXPOSE 端口号/协议 默认协议为TCP |
env | 设置指令 指定环境变量,它可以被其后的add、copy等调用 可以通过docker inspect查看这个环境变量,也可以通过在docker run -- env key=value时设置或修改环境变量 如果你要设置多个环境变量,为了美观,你可以使用\ 来进行换行。多个环境变量的隔开,使用空格进行隔开的,如果某个环境变量的值是由一组英文单词构成,那么你可以将其使用"" 进行圈起来 值得注意的是,如果你想通过CMD 或者ENTRYPOINT 指令的exec格式来打印环境 CMD ["echo", $MODE] CMD ["echo", "$MODE"] 上面这样都是不能正确输出环境变量的值的,你可以改成exec格式来执行shell命令,如下 CMD ["sh", "-c", "echo $MODE"] | 调用格式$name或者${name} |
wokrdir | 设置指令 使用WORKDIR 指令来制定工作目录(或者称为当前目录),以后各层操作的当前目录就是为指定的目录,如果该目录不存在,WORKDIR 会自动帮你创建目录 WORKDIR 指令可以通过docker run 命令中的-w 参数来进行覆盖 | |
user | 设置指令 指令用于将会用以什么样的用户去运行默认为root 可以指定用户名或者UID,组名或者GID,或者两者的结合 USER 指令可以在docker run 命令中的-u 参数进行覆盖 后续的 RUN 也会使用指定用户。 当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:RUN groupadd -r postgres && useradd -r -g postgres postgres 。要临时获取管理员权限可以使用 gosu ,而不推荐 sudo | |
healthcheck | 告诉Docker该如何判断容器的状态是否正常,这是1.12引入的新指令 在没有HEALTHCHECK 指令之前,Docker引擎只可以通过容器内主进程是否退出来判断容器状态是否异常。很多情况下这没有问题,但是如果程序进入了死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法继续提供服务了。在1.12之前,Docker引擎不会检测到容器的这种状态,从而不会重新调度,导致可能容器已经无法提供服务了却仍然还在接收用户的请求。 HEALTHCHECK 指令只可以出现一次,如果有多个HEALTHCHECK 指令,那么只有最后一个才会生效 | HEALTHCHECK [options] CMD <命令>:检查容器健康状态的命令 HEALTHCHECK NONE:如果基础镜像有健康检查指令,这一行将会屏蔽掉其健康检查指令 HEALTHECHECK支持下列选项: –interval=<间隔>:两次检查的时间间隔,默认为30s –timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查将会判定 为失败,默认为30s –retries=<次数>:当连续失败指定次数之后,则将容器状态视为unhealthy ,默认为3次 |
onbuild | ONBUILD 是一个特殊的指令,它后面跟着的是其他指令,比如COPY 、RUN 等,而这些命令在当前镜像被构建时,并不会被执行。只有以当前镜像为基础镜像去构建下一级镜像时,才会被执行 | ONBUILD <其他指令> |
shell | 指定Dockerfile中 【 shell form 】命令的默认shell。 Linux中默认shell为 【 “/bin/sh”, “-c”】 | |
arg | 构建参数ARG 和ENV 指令一样,都是设置环境变量。与之不同的是,ARG 设置的环境变量只是在镜像构建时所设置的,在将来容器运行时是不会存在这些环境变量的。但是不要因此就用ARG 来保存密码之类的信息,因为通过docker history 还是能够看得到的。ARG 指令与ENV 指令的使用类似 ARG 构建参数可以通过docker run 命令中的--build-arg 参数来进行覆盖 | |
cmd | 设置指令。 Docker不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,就需要指定运行的程序及参数。CMD 就是指定默认的容器主进程的启动命令的 每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。 如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令 这里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。 原因是参数传递后,docker解析的是一个JSON array 一些命令在加上sh -c 之后,有可能会发生意想不到的错误,因此在Dockerfile中使用RUN 指令时,更加推荐使用exec 格式!最后需要牢记,使用docker run 命令指定要执行的命令可以覆盖RUN 指令,如果我们的docker run 中指定了我们将要执行的命令,并且在Dockerfile中也指定了CMD命令 | exec格式CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式; shell格式CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用。 CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数,如果CMD指令使用上面的形式,那么Dockerfile中必须要有配套的ENTRYPOINT |
entrypoint | 设置指令 指定容器运行程序及参数 配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。 每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效 ENTRYPOINT 也更加推荐使用exec 格式,ENTRYPOINT 在docker run 命令中同样也可以进行指定,只不过比CMD 指令来的繁琐一些,需要指定--entrypoint 参数。同样,在docker run 命令中指定了--entrypoint 参数的话,会覆盖Dockerfile中ENTRYPOINT 上的指令。 该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用。 当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖,只有最后一个CMD或者ENTRYPOINT有效。 CMD echo “Hello, World!” ENTRYPOINT ls -l 另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分; ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数。 CMD [ "-l" ] ENTRYPOINT [ "/usr/bin/ls" ] | exec格式ENTRYPOINT ["executable", "param1", "param2"] shell格式ENTRYPOINT command param1 param2 (shell中执行) |
| | |
| | |
| | |