Dockerfile是一个普通的文本文件,里面包含了许多可以在命令行接口上执行的用来构建镜像的相关指令,我们通过docker build指令就可以读取Dockerfile文件中的指令并执行自动化镜像构建。
一般情况下,Dockerfile文件可分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时的执行指令,其基本结构如文件1所示。
文件1 Dockerfile
1 #定义基础镜像信息
2 FROM ubuntu
3 # 定义该镜像的维护者信息
4 MAINTAINER docker_user docker_user@email.com
5 # 一些镜像操作指令
6 RUN echo “deb http://archive.ubuntu.com/ubuntu/ raring main universe”
7 >> /etc/apt/sources.list
8 RUN apt-get update && apt-get install -y nginx
9 RUN echo “\ndaemon off;” >> /etc/nginx/nginx.conf
10 # 当容器启动时要执行的指令
11 CMD /usr/sbin/nginx
从文件1可以看出,Dockerfile文件由多条命令语句组成,每条语句都代表一个指令。其中以“#”开头的指令表示注释,另外当一条指令过长时,可以使用反斜杠“\”进行指令换行,这样一条较长的指令就会被分为多行显示。
小提示:
Dockerfile文件是Docker构建镜像的脚本文件,名字可以自定义,但在构建镜像时默认使用的是Dockerfile文件。当定义为其他名称时,在进行镜像构建时,必须指定该脚本文件的位置和名称。因此,通常情况下,推荐直接使用默认的Dockerfile进行命名。
在编写Dockerfile脚本文件时,开发者根据实际需要会使用到各种指令,如FROM、CMD、ADD等,这些常用指令及其说明如表1所示。
表1 Dockerfile常用指令
指令 说明
FROM 指定基础镜像
MAINTAINER 指定镜像维护者信息
RUN 用于执行指定脚本命令
CMD 指定启动容器时执行的命令
EXPOSE 指定容器暴露的端口
ENV 指定环境变量
ADD 将文件从宿主机复制到容器指定位置,同时对压缩文件有自动解压功能
COPY 将文件从宿主机复制到容器指定位置
ENTRYPOINT 设置容器启动时需要运行的命令
WORKDIR 为后续的如RUN、CMD、ENTRYPOINT、COPY、ADD指定工作目录
在表1中,列举了Dockerfile文件中的一些常用指令,并分别对其作用进行了简要说明。为了帮助读者更好的掌握这些指令的使用,接下来将对这些常用指令的使用进行详细讲解。
1.FROM
FROM指令用于初始化一个新的镜像构建阶段,同时为之后的指令设置一个基础镜像。设定的基础镜像可以从DockerHub镜像注册中心或者本地镜像列表选取,当本地镜像列表中存在设定的镜像就会直接使用本地镜像,否则会先从远程镜像注册中心拉取到本地再使用。
FROM指令使用的语法格式如下。
FROM
FROM :
具体示例如下。
FROM ubuntu
FROM ubuntu:16.04
在使用FROM指令时,需要注意以下几点。
● 一个有效的Dockerfile文件必须以FROM指令开头(除了ARG指令);
● 为了创建多重镜像或者互相依赖的镜像,在同一个Dockerfile文件中可能会出现多个FROM指令;
● 参数是可选的,其作用主要是进一步对镜像区分,例如版本、型号等(如上述示例中的ubuntu:16.04就表示版本号为16.04的ubuntu)。如果没有使用该参数,则默认是latest;如果设置的参数不存在,则构建镜像也会失败。
2.MAINTAINER
MAINTAINER指令用于指定当前构建的镜像维护者信息,该指令没有具体的格式要求,通常建议使用用户名和邮箱进行标识,具体示例如下。
MAINTAINER "shitou"shitou@163.com
3.RUN
RUN指令用于执行指定的脚本命令,有两种格式,其语法格式如下。
RUN
RUN [“executable”, “param1”, “param2”]
前者将在 shell 终端中运行命令,即 /bin/sh -c;后者则使用 exec 执行。指定使用其他终端可以通过第二种方式实现,例如 RUN ["/bin/bash", “-c”, “echo hello”]。
其中每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。如果要执行多条RUN指令,通常会将多条RUN指令合成一条,并使用斜杠“\” 来换行,这样将减小所构建的镜像的体积。
4.CMD
CMD指令用于指定启动容器时执行的命令,该指令有三种格式,其语法格式如下。
CMD [“executable”,“param1”,“param2”] #使用 exec 执行,也是推荐方式;
CMD command param1 param2 #在 /bin/sh 中执行,提供给需要交互的应用;
CMD [“param1”,“param2”] #提供给 ENTRYPOINT 的默认参数;
需要注意的是,在使用CMD指令时,每个 Dockerfile 只能有一条 CMD 指令,如果有多条CMD指令,则只有最后一条生效。如果用户启动容器时指定了运行的指令,则会覆盖掉CMD指定的指令。
5.EXPOSE
EXPOSE指令用于声明容器内部暴露的端口号,供容器访问连接使用,其语法格式如下。
EXPOSE […]
6.ENV
ENV指令用于为下文设定一个环境变量,该变量值在后续指令或内联文件中都可以使用。ENV指令有两种语法格式,具体如下。
ENV
ENV = = …
在上述两种语法格式中,第一种格式为一个属性设置唯一的属性值,属性第一个空格之后的所有字符串(包括空格、引号)都将被视为该属性的值;第二种格式允许同时为多个属性赋值,而这种方式里面的引号、反斜杠等将被解析掉。
7.ADD
ADD指令用于复制指定的 src资源文件到容器中的 dest目录下,复制的资源可以是文件、目录以及远程URLs资源。其语法格式如下。
ADD …
在使用ADD指令时,复制的src资源文件必须是当前上下文目录或其子目录,而复制的内容实际上是该目录下的所有内容,其中包括文件系统元数据,而目录本身不会被复制。当dest目录不存在时,会在复制文件时自动创建。需要注意的是,当使用ADD指令复制的文件是一个压缩包时,ADD指令会在复制好该文件后,自动进行解压。
在使用ADD指令时,复制的src资源文件路径允许使用通配符,而dest目标目录可以使用绝对路径,也可以使用预先用WORKDIR指令定义的相对路径。
8.COPY
COPY指令的作用与ADD指令类似,都是复制指定的src资源文件到容器中的 dest目录下。区别在于,COPY指令不能复制远程URL路径文件,也不能解压文件,而ADD指令则可以。其语法格式如下。
COPY …
9.ENTRYPOINT
ENTRYPOINT指令是配置容器启动后执行的命令,每个Dockerfile中只能有一个ENTRYPOINT,当指定多个ENTRYPOINT指令时,只有最后一个生效。该指令有两种语法格式,其语法格式如下。
ENTRYPOINT [“executable”, “param1”, “param2”] (exec 格式, 推荐的)
ENTRYPOINT command param1 param2 (shell 格式)
10.WORKDIR
WORKDIR指令用于为后续的指令(如RUN、CMD、ENTRYPOINT、COPY、ADD)指定工作目录,在同一个Dockerfile文件中可以多次使用WORKDIR指令,其语法格式如下。
WORKDIR /path/to/workdir
至此,关于Dockerfile文件中的常用指令已介绍完毕,读者可以根据自身实际情况选取使用。Dockerfile的更多指令可以参考Dockerfile官网学习,具体地址为https://docs.docker.com/engine/reference/builder/#arg。
在实际情况下,Docker在读取应用上下文中的Dockerfile文件进行镜像构建之前,都会先查看当前应用上下文中是否包含一个名为.dockerignore的文件,如果该文件存在,则Docker会先将.dockerignore文件中声明的文件或目录进行排除,然后再读取Dockerfile进行镜像构建。使用.dockerignore将有助于在进行文件复制过程中避免向进程中加入过大或者敏感的无用文件和目录。
.dockerignore文件同Dockerfile文件一样,也是一个文本文件。二者的主要区别在于.dockerignore中存放的是被排除的文件,而Dockerfile中存放的是需要执行的指令。
接下来,通过一个简单的示例来讲解.dockerignore文件内容的编写,如文件1所示。
文件1 .dockerignore
1 # comment
2 /temp
3 //temp*
4 temp?
在文件1中,第1行代码表示注释内容,其余3行代码均为被排除的文件。从被排除文件的编写方式可以看出,.dockerignore文件中可以使用通配符排除匹配路径下的文件。
下面针对使用通配符排除匹配路径下的文件进行具体分析。
● /temp:排除根目录下任意子目录中所有名字以temp开头的文件或目录。例如文件/somedir/temporary.txt会被排除。
● //temp*:排除根目录下任意两级子目录中所有名字以temp开头的文件或目录。例如文件/somedir/subdir/temporary.txt会被排除。
● temp?:排除根目录下名字以temp开头,后面为任意一个字符的文件或目录。例如目录/tempa和/tempb都将被排除。
小提示:
在前面几个小节中,具体介绍了Dockerfile的基本结构和常用指令,读者想要写出好的Dockerfile文件就必须对具体的需求、一些shell命令以及注意事项有所了解,这些内容可以通过参考官方文档学习,其地址https://rock-it.pl/how-to-write-excellent-dockerfiles/。