一、DockerFile介绍
1、DockerFile 介绍
DockerFile 是一种能够被Docker 程序解释的文件(一般为了方便理解称之为"剧本")。
DockerFile 由一条一条的指令组成,并且有自己的书写格式和支持的命令。当我们需要在容器
镜像中指定自己额外的需求时,只需要在 DockerFile 上添加或修改指令,然后通过
docker build 生成我们自定义的镜像(imahe)。如下图所示:

2、DockerFile 文件基本构成
1)基础镜像信息
2)维护者信息
3)镜像操作指令
4)镜像容器启动时执行指令
二、DockerFile 指令介绍
1、DockerFile 指令分类
DockerFile 的指令主要分为 构建类指令 和 设置类指令;
构建类指令主要用来构建镜像image,其指令的操作不会在image的容器上执行,如:FROM
、MAINTAINER、RUN、ENV、ADD、COPY 都是构建类指令。
设置类指令主要用于设置镜像image的属性信息,其指令的操作将在image的容器上执行,
如:CMD、ENTRYPOINT、USER、EXPOSE、VOLUME、WORKDIR、ONBUILD 都是
设置类指令。
2、DockerFile 指令说明
2.1、指令说明
指令 | 说明 |
---|---|
FROM | 基础镜像,当前新镜像是基于哪个镜像的,有继承的意味 |
MAINTAINER | 镜像维护者的姓名和邮箱地址 |
RUN | 容器构建时需要运行的命令 |
EXPOSE | 当前容器对外暴露的端口 |
WORKDIR | 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点 |
ENV | 用来在构建镜像过程中设置环境变量 |
ADD | 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包 |
COPY | 类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置 COPY src dest COPY ["src","dest"] |
VOLUME | 容器数据卷,用于数据保存和持久化工作 |
CMD | 指定一个容器启动时要运行的命令 Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换 |
ENTRYPOINT | 指定一个容器启动时要运行的命令 ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数 |
ONBUILD | 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发 |
2.2、指令详细介绍
通过 man docker file 命令可以查看到DockerFile指令的详细说明,这里简单介绍下常用
的指令。
2.2.1、FROM
FROM 指令 用于指定其后构建 新镜像 是所使用的基础镜像。
FROM 指令 必须是 DockerFile 文件中的收条命令。
FROM 指令 所指定的基础镜像image可以是远程官方仓库中的也可以是本地仓库中的(一
般是Linux或CentOS),优先本地仓库中的镜像。
FROM 指令使用格式:
FROM <image镜像>:<tag版本标签>
如:FROM centos:latest
2.2.2、RUN
RUN 指令用于设置在构建镜像过程中执行的命令,有以下2种格式:
1)shell格式
命令格式:RUN <命令>
例如:RUN echo 'kubemsb' > /var/www/html/index.htm
2)exec 格式
命令格式:RUN ["可执行文件","参数1","参数2"]
例如:RUN ["/bin/bash","-c","echo kubemsb > /var/www/html/index.htm"]
注意:
按优化的角度来讲:当有多条需要执行的run命令时,不要使用多条RUN、尽量使用
'&&' 或 '\' 符号连接成一行。因为多条RUN命令会让镜像建立多层(镜像变臃肿了),
如下图所示:

2.2.3、CMD
CMD命令不同于 RUN 命令,CMD命令用于在容器启动时所要执行的命令,而RUN 用于
指定镜像构建时所要执行的命令、
CMD 命令格式有3种,如下所示:
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
注意:
1)每个DockerFile只能有一条CMD命令。如果指定了多条CMD命令,只有最后一条
CMD命令会被执行
2)如果容器启动时指定了运行命令,则会覆盖CMD指定的命令。
3)什么是容器启动时指定的运行命令?
启动容器时指定的运行命令,如:docker run -d 镜像名 运行命令
2.2.4、EXPOSE
EXPOSE命令用于指定容器在运行时监听的端口,可以一次监听多个端口
命令格式:EXPOSE <port> [<port>...]
例如:EXPOSE 80 3306 8080
注意:
EXPOSE 监听的端口,在容器启动时需要通过参数 -p 映射到宿主机上后外部才能访问
2.2.5、ADD
ADD 命令用于将宿主机上的文件拷贝到构建的自定义镜像image 中
格式:ADD <src> <dest>
src:可以是一个本地文件或压缩文件,也可以是一个url,如果src是一个url,那么ADD 就
相当于wget 命令
dest:dest 路径的填写可以是容器内的绝对路径,也可以是相对工作目录的相对路径
2.2.6、ENV
ENV 命令用于指定一个环境变量
格式:ENV <key> <value> 或者
ENV <key>=<value>
例如:ENV JAVA_HOME /usr/local/jdk/jdk-XX
2.2.7、COPY
COPY命令与 ADD 命令功能一样,都是将宿主机上的文件拷贝到构建的自定义镜像
image 中,不同的是COPY的源文件src只能是本地文件
格式:COPY <src> <dest>
2.2.8、ENTRYPOINT
ENTRYPOINT 与 CMD 非常相似,都是用于指定在容器启动时需要实行的命令。
ENTRYPOINT 与 CMD 相同点:
I)一个DockerFile 只能写一条,如果写了多条,那么只有最后一条才生效;
II)都是在容器启动时执行;
ENTRYPOINT 与 CMD 不同点:
I)如果用户启动容器时指定了运行命令,ENTRYPOINT不会被运行命令覆盖,而 CMD
会被运行命令覆盖
格式有2种:
I)ENTRYPOINT ["executable","param1","param2"]
II)ENTRYPOINT command param1 param2
2.2.9、VOLUME
VOLUME 命令用于把宿主机的目录与容器中的目录映射。
使用时只指定挂载点,docker容器中的目录为自动生成的。
格式:VOLUME ["<mountpoint>"]
2.2.10、USER
USER 命令用于设置启动容器的用户(如:Oracle需要Oracle用户操作),可以是
用户名或UID。
例如:USER daemon 或 USER 1001
注意:
如果容器设置了以 daemon 用户去运行,那么 RUN,CMD 和 ENTRYPOINT都会
以这个用户去运行;镜像构建完成后,通过docker run 运行容器时,可以通过参数
-u 来覆盖锁指定的用户
2.2.11、WORKDIR
WORKDIR 命令用于设置工作目录,类似于cd 命令。
不建议使用RUN cd /root,建议使用 WORKDIR,如:WORKDIR /root
三、DockerFile 执行流程及生成镜像的一般步骤
3.1、DockerFile 生成镜像的基本步骤
使用 DockerFile 生成对应镜像一般需要以下步骤:
1)在指令目录创建一个文件夹(目标)
2)在该文件夹中编写 DockerFile 文件
3)使用 "docker build" 命令构建镜像
4)docker run 使用构建的镜像启动容器
如下图所示:

3.2、DockerFile文件中的指令需要满足以下规则

3.3、DockerFile 执行流程
docker 执行一个 DockerFile 脚本的流程大致如下:
1)docker从基础镜像运行一个容器
2)执行一条指令并对容器作出修改
3)执行类似docker commit的操作提交一个新的镜像层
4)docker再基于刚提交的镜像运行一个新的容器
5)执行dockerfile中的下一条指令直到所有指令都执行完成
3.4、DockerFile、Docker镜像和Docker容器之间的关系
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不
同阶段,即:
I)Dockerfile是软件的原材料
II)Docker镜像是软件的交付品
III)Docker容器则可以认为是软件的运行态
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺
一不可,合力充当Docker体系的基石,如下图所示:

1)Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。
Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、
动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务
和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等
2)Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,
当运行 Docker镜像时,会真正开始提供服务
3)Docker容器,容器是直接提供服务的
四、Dockerfile 使用案例
1、以构建Tomcat 为例来看下 DockerFile 的使用步骤
1.1、在指定目录下创建一个目录,如:tomcatdir
1.2、在目录 tomcatdir 中上传 jdk 和 tomcat 的安装包,
1.3、在目录 tomcatdir 中创建DockerFile 文件,DockerFile内容如下:

cs
FROM centos:centos7
MAINTAINER bobo<[email protected]>
#把宿主机当前上下文的hello.txt拷贝到容器/usr/local/路径下
COPY hello.txt /usr/local/hello.txt
#把java与tomcat添加到容器中
ADD jdk-8u73-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.71.tar.gz /usr/local/
#安装vim编辑器
#RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_73
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.71
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.71
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-8.0.47/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-8.0.47/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-8.5.71/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.0.47/bin/logs/catalina.out
1.4、构建tomcat 镜像
执行命令 docker build -f Dockerfile -t image-tomcat . 来构建镜像,
其中 image-tomcat 是镜像名称,-f 指定DockerFile 文件


1.5、启动容器
1)执行下面命令来启动容器:
docker run -it -p 9080:8080 --name docker-tomcat -v /root/DockerFile/tomcatdir/test:/usr/local/apache-tomcat-8.5.71/webapps/test -v /root/DockerFile/tomcatdir/tomcatlogs/:/usr/local/apache-tomcat-8.5.71/logs -d image-tomcat

2)测试
在浏览器中输入 Apache Tomcat/8.5.71 访问tomcat ,看容器是否运行成功,
如下图所示:
