简介
Dockerfile可以认为是Docker镜像的描述文件,是由一系列命令和参数构成的脚本。主要作用是用来构建docker镜像的构建文件。
dockerfile执行build命令时,是从上倒下依次执行的,dockerfile的基本组成部分如下。
主要部分 | 代表命令 |
---|---|
基础镜像信息 | FROM |
维护者信息 | MAINTAINER |
镜像操作指令 | RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME、ENV等 |
容器启动时执行指令 | CMD、ENTRYPOINT |
dockerfile常用命令
保留字 | 作用 |
---|---|
FROM | 当前镜像是基于那个镜像的 |
LABEL | 用于添加镜像的元数据 |
MANTAINER | 镜像维护者的姓名和邮箱 |
EXPORT | 当前容器对外暴漏出的端口 |
WORKDIR | 指定在创建容器后,终端默认登陆进来的工作目录 |
ARG | 指令定义了一个变量,仅用于构建阶段,无法驻留在镜像中 |
ENV | 用来为构建镜像设置环境变量,这个值将出现在构建阶段中所有后续的环境中在 |
ADD | 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar包 |
COPY | 类似于ADD,拷贝文件和目录到镜像中,将从镜像上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径> |
VOLUME | 容器数据卷,用于数据保存和持久化工作 |
RUN | 构建镜像时需要的运行命令,用于指定 docker build 过程中要运行的命令。 |
CMD | 指定一个容器启动时要运行的命令,Dockerfile中可以有多个CMD命令,但只有最后一个生效,CMD 在docker run 时运行,而非docker build; |
ENTRYPOINT | 指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及其参数 |
FROM
功能为指定基础镜像,并且必须是第一条指令。
如果不以任何镜像为基础,那么写法为:FROM scratch。
同时意味着接下来所写的指令将作为镜像的第一层开始
语法:
FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
示例:
FROM java:8
LABEL
label用于添加镜像的元数据,采用key-value的形式。
语法:
LABEL <key>=<value>
示例:
LABEL "miantainer"="github.cn"
LABEL "version"="v1.0"
LABEL "author"="yanyu"
#为了防止创建三层,我们最好通过一个标签来写。
LABEL "miantainer"="github.cn" \
"version"="v1.0" \
"author"="yanyu"
MANTAINER
镜像维护者的姓名和邮箱(废弃)
语法:
MAINTAINER <name>
EXPORT
用于指定构建的镜像在运行为容器时对外暴露的端口
语法:
格式:
EXPOSE <port> [<port>...]
示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
注: EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
如果没有暴露端口,后期也可以通过-p 8080:80方式映射端口,但是不能通过-P形式映射
注意,EXPOSE只是告诉dockerfile的阅读者,我们构建的镜像需要暴露哪些端口,只是一个信息。在容器中还是需要通过-p选项来暴露端口。
WORKDIR
用来为Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录,如果WORKDIR不存在,即使它没有在任何后续Dockfile指令中使用,它也将被创建;
语法:
格式:
WORKDIR /path/to/workdir
示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
注意:
1. WORKDIR指令可以在Dockerfile中多次使用,如果提供了相对路径,则该路径将于先前WORKDIR指令的路径行对
2. 通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY
等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
ARG
指令定义了一个变量,仅用于构建阶段,无法驻留在镜像中。
语法:
格式:
ARG <name>[=<default value>]
示例:
ARG site
ARG build_user=www
ARG指令定义了一个变量,我们可以在docker build通过使用–build-arg = 标志的命令将其传递给构建器。
-
如果ARG指令具有默认值并且在构建时没有传递任何值,则构建器使用默认值。
-
在多阶段构建应该添加多个ARG
-
ENV变量会覆盖ARG变量
-
与ENV变量相比,ARG变量多用于构建,无法驻留在镜像中。
ENV
用来为构建镜像设置环境变量,这个值将出现在构建阶段中所有后续的环境中。
语法:
格式:
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy
Dockerfile示例:
FROM busybox
ENV FOO=/bar \
FO1=/bar1
WORKDIR ${FOO} # WORKDIR /bar
ADD . $FOO # ADD . /bar
COPY \$FO1 /quux # COPY $FOO /quux
当然我们也可以在启动容器时添加环境变量
docker run --env <key>=<value>
另外如果只需要在镜像构建期间使用环境变量,更好的选择是使用ARG参数来处理
ADD
用来从context上下文复制新文件、目录或远程文件url,并将它们添加到位于指定路径的映射文件系统中。
语法:
ADD hom* /mydir/ 通配符添加多个文件
ADD home?.txt /mydir/ 通配符添加
ADD test.txt relativeDir/ 指定相对路径
ADD test.txt /absoluteDir/ 指定绝对路径
COPY
功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
格式:
COPY src desc
COPY ["<src>",..."<dest>"]
VOLUME
可实现挂载功能,可以将内地文件夹或者其他容器种得文件夹挂在到这个容器种
语法:
格式:
VOLUME ["/path/to/dir"]
示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"
注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1 卷可以容器间共享和重用
2 容器并不一定要和其它容器共享卷
3 修改卷后会立即生效
4 对卷的修改不会对镜像产生影响
5 卷会一直存在,直到没有任何容器在使用它
RUN
构建镜像时需要的运行命令,用于指定 docker build 过程中要运行的命令。
语法:
格式:
RUN <command>
RUN ["exec",param1,param2]
示例:
RUN yum install -y gcc
# 当我们不想使用默认shell是可以采用exec形式实现
RUN ["/bin/bash","-c","yum install -y gcc"]
# 当然,exec形式可以不使用shell
RUN ["yum","install","-y","gcc"]
EXEC形式被解析为一个JSON阵列,所以必须使用双引号
CMD
指定一个容器启动时要运行的命令,Dockerfile中可以有多个CMD命令,但只有最后一个生效,
语法:
格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
示例:
CMD echo "This is a test." | wc -l
CMD ["/usr/bin/wc","--help"]
注:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
示例:
#dockerfile文件配置
CMD echo hello
#构建镜像后,docker run 不添加参数,启动容器
[root@localhost dockerfiles]# docker run centos:v1
打印结果:hello
#当我们在docker run 添加参数后
[root@localhost dockerfiles]# docker run centos_env:v1 echo
打印结果:container
显然我们CMD命令echo hello已被docker run中的参数echo container取代。
与RUN相比,CMD在构建时不会执行任何操作,主要用于指定镜像的启动命令。CMD的启动命令可以被docker run 参数代替。
ENTRYPOINT
exec首选和shell形式:
语法:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
示例:
ENTRYPOINT echo hello container
构建镜像并启动容器,可以看到docker run 中的参数并未取代ENTRYPOINT
[root@localhost dockerfiles]# docker run myimage:v1.0 echo hello docker
hello container
ENTRYPOINT 和CMD很相似,都是指定启动命令,不同之处在于ENTRYPOINT 指定的命令无法被docker run 参数取代。
这指令优秀的另一个地方在于可以和CMD指令做交互。让容器以应用或者服务运行。
ENTRYPOINT ["java", "-jar"]
CMD ["app.jar"]
运行容器
# 替换app.jar为appnew.jar,最终执行的命令为java -jar appnew.jar
[root@localhost dockerfiles]# docker run myimage:v1.0 appnew.jar
构建命令
在包含Dockerfile的文件夹下运行如下命令
docker build -t my:lastest .