Dockerfile文件详解
Docker应用之创建镜像 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中简单介绍了Dockerfile创建镜像,本文将详细介绍Dockerfile的基本结构、指令。
一、基本结构
如果具备一定Linux命令行基础,编写Dockerfile会更轻松——因为整体而言,Dockerfile就是一份自动化的Linux命令集。同时基于此,在写Dockerfile的过程中,需要模拟一遍命令的执行过程,避免因命令行写错而重新构建的情况(构建比较费时)。
命令规则:Dockerfile虽然可以命名为其他名字,但是一般情况不推荐修改除非同一个文件夹下存在多个Dockerfile文件。因为Dockerfile本身只是一份文本,不带特殊权限改为其他名字后会导致其他人可能仅看文件名不看内容不容易分;而且部分自动化构建工具甚至默认使用Dockerfile这个名字。
书写规则:一份标志的Dockerfile文件中应包含指令、注释等内容,构建指令应使镜像尽量干净没有垃圾文件——基于其是Linux命令集,可以想象Dockerfile就是一份指定文件名指定文件格式内容的脚本:
1、自动化:Dockerfile全程无交互(不同于其他脚本可能还给选择让在终端做出选择),所以整个构建过程需要保证命令集能够一直持续不断执行下去。
2、顺序:Dockerfile构建过程默认就是之上而下,所以对其中的命令编写要考虑顺序问题。
3、清理:构建镜像的过程中会产生很多临时文件,对于这些临时文件需要通过在Dockerfile文件最后写上清理系统的命令处理。
4、易读:对于这个作为IT从业人员是基本的职业素养。
二、指令
通过查看官网上已有镜像的Dockerfile文件可以发现一个规律就是所有命令默认均是大写。
1、FROM
FROM指令表示将来构建的镜像来自哪个镜像,也就是使用哪个镜像作为基础进行构建。其必须是这个Dockerfile第一句有效指令。如下示例:
2、MAINTAINER
这条指令主要指定维护者信息,方便他人寻找作者。
3、RUN
RUN指令用来在Docker的编译环境中运行指定命令。其会在shell或者exec的环境下执行命令,具体格式如下:
shell:RUN sh命令 ……
exec:RUN [程序名, 参数1, 参数2,……]
需要注意的是exec格式不会触发shell,所以其可以免除运行/bin/sh的开销在没有bash的镜像中执行同时可以避免错误的解析命令字符串。其也具有一定缺点就是如$HOME这样的环境变量无法使用。
4、ENV
ENV指令用来指定在执行docker run命令运行镜像时,自动设置的环境变量。这个环境变量可以在后续任何RUN指令中使用,并在容器运行时保持。而且可以通过docker run命令的-e参数来修改。
5、COPY
这条指令用来将本地的文件或文件夹复制到镜像的指定路径下,类似单向的docker cp(个人理解)。
6、ADD
该指令与COPY作用类似,但实现不同。ADD指令可以从一个URL地址上下载内容复制到容器的文件系统中,还可以两压缩打包格式的文件解压后复制到指定路径。
在相同的复制命令下,使用ADD构建镜像的大小比COPY构建的镜像要大,所以如果只是单纯的复制文件尽可能用COPY。
7、EXPOSE
这条指令用于标明这个镜像中应用将会侦听某个端口,并希望能将这个端口映射到主机的网络界面上。
8、CMD
CMD提供了容器默认的执行命令。Dockerfile只允许使用一次CMD指令,所以如果有多个CMD指令时只有最后一个指令生效(后面的指令会覆盖之前的所有指令)。一般来说这也是整个Dockerfile脚本的最后一条指令——当Dockerfile已经完成了所有环境的安装与配置,通过CMD指令来指示docker run命令运行镜像时要执行的命令,格式如下:
CMD [executable,param1, param2]
需要注意的是,docker run 命令可以覆盖CMD命令。CMD与ENTRYPOINT的功能极为类似。区别在于:如果docker run 后面出现与CMD指定相同的命令,那么CMD会被覆盖;而ENTRYPOINT会把容器名后面的所有内容都当成参数传递给其他指定的命令(不会覆盖)。另外,CMD指令还可以单独作为ENTRYPOINT指令的可选参数,共同组合成一条完成的启动命令。
9、ENTRYPOINT
这个指定与CMD很相似,其相当于把镜像变成一个固定的命令工具,它一般是不可能通过docker run 来改变的。
10、VOLUME
该指令用来向基于镜像创建的容器添加数据卷(数据卷相关具体可参考Docker核心原理之数据卷 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com))。数据卷可以在容器建共享和重用,且其修改是立即生效的。
VOLUME可以在docker run 中使用,如果run命令中没有使用则默认不会在宿主机gauze这个数据卷。如果Dockerfile中没有设置数据卷,也可以在docker run中进行设置。在Dockerfile中声明数据卷有助于迅速定位需要保存数据的目录位置。
11、USER
USER指定运行容器时的用户名或UID(默认为root)。该指令可以在docker run命令中通过-u选项来覆盖。其主要应用场景在于,当服务不再需要管理员权限时可以通过该命令指定运行用户。
12、WORKDIR
该指令指定RUN、CMD与ENTRYPOINT命令的工作目录。同时,可以通过docker run -w标志在运行时覆盖指令指定的目录。
13、ONBUILD
该指令为设置二次构建指令——指定在构建镜像时并不执行而是在它的子镜像中执行。
14、LABLE
该指令添加元数据到镜像。每一个标签会生成一个layer,所以经理使用一个LABLE标签。
15、ARG
该指令定义了一个变量,用户可以在构建时使用,效果同docker build --build-arg一样,可以在构建时设定参数,这个参数只会在构建时存在——其与ENV类似,不同的是ENV不会在镜像构建后消失而ARG会消失无效。
16、STOPSIGNAL
该指令允许用户定制化运行docker stop时的信号。
17、HEALTHCHECK
这是一个健康检查指令,用来检查将来容器启动运行时是否正常。
18、SHELL
在Docker构建过程中,Linux下默认会使用/bin/sh作为shell环境。但是有时需要在其他shell环境中执行RUN的内容,这就需要用SHELL指令提醒Docker更换shell环境。