zoukankan      html  css  js  c++  java
  • docker系列七之Dockerfile

    Dockerfile

    一. Dockerfile是什么

        Dockerfile是docker中镜像文件的的描述文件,说的直白点就是镜像文件到底是由什么东西一步步构成的。例如我们在淘宝上买了一件商品,但是这个商品需要组装才能使用,于是卖家就给了你一张图纸,你就按照图纸一步一步的组装起来,然后就成了你所需要的样子。那么Dockerfile就是这张图纸,镜像文件就是你需要的商品。Dockerfile名字可以随便命名,但是不建议你这做,还是按照规范来使用,首字母要大写。下面给出我们前几个章节使用到的centos为例,来看看它的Dockerfile是怎么样的,如下图所示:     

                                   

    二. Dockerfile、镜像、容器

        Dockerfile:是镜像的构建文件,描述的镜像是一步步怎么来的。

      镜像:是通过Dockerfile做出来的,包含操作系统基础文件和软件运行环境,它使用分层的存储方式。

      容器:是运行起来的镜像,简单理解,Docker镜像相当于程序,容器相当于进程。

    三. Dockerfile的基本语法及执行流程

    3.1 Dockerfile的基本语法

       a.每个保留字必须放在每一行的开头,可以大写也可以小写,但是建议大写;

      b.指令按照顺序,从上往下依次执行;

      c.#表示注解;

      d.每条执行指令都会创建一个新的镜像,并且执行提交。

    3.2 Dockerfile的执行流程

       a.docker从基础镜像中执行一个容器; 

       b.执行一条指令对镜像进行修改;

       c.执行docker commit命令,提交新的镜像;

       d.在基于刚刚提交的镜像运行一个新的容器;

       e.执行Dockerfile中的下一条指令,按照b、c、d依次循环下去,知道所有的指令执行完毕。

    3.3 演示讲解

    FROM centos                              #指定要生成的镜像的基础镜像,开头第一句话必须也只能是FROM
    MAINTAINER  zhengjingmao@163.com         #指定作者是谁
    RUN yum install -y vim                   #执行 yum install -y vim 命令,安装vim
    RUN yum install -y net-tools             #执行 yum install -y net-tools, 安装net-tools工具
    WORKDIR /dev/ #启动容器后,如果启动交互模式,直接进入到哪个目录 CMD [
    "/bin/bash"] #启动容器的时候,进入到/bin/bash这种命令行

        如上代码所示,FROM、MAINTAINER、RUN、WORKDIR、CMD均为关键字,按照标准的规范需要大写;FROM centos表示我们的基础镜像是centos,然后会启动centos这个容器,执行第二行代码又会生成新的镜像文件,然后提交,周而复始。

    四. Dockerfile关键字

    关键字 作用
    FROM 指定基础镜像
    MAINTAINER 作者的信息
    RUN 执行什么命令
    EXPOSE 容器对外暴露的端口
    WORKDIR 进入到容器后进入到哪个目录
    ENV 配置环境变量
    ADD 将文件拷贝到镜像中并解压
    COPY 将文件拷贝到镜像中
    VOLUME 配置数据卷
    CMD 容器启动时候执行的命令
    ENTRYPOINT 容器启动时候执行的命令

          a.ADD指令,我们现在定义这样一个Dockerfile,代码如下所示:

    FROM centos
    MAINTAINER  zhengjingmao@163.com
    RUN mkdir /datas
    ADD jdk-8u60-linux-x64.tar.gz /datas/
    WORKDIR /datas/
    CMD ["/bin/bash"]

         首先必须将jdk-8u60-linux-x64.tar.gz文件拷贝到Dockerfile同级目录下,如下图所示:

                                                            

         执行命令:docker build -t mycentos .  构建mycentos镜像,如下图所示:

                                                              

          然后启动容器,进入到 /datas/目录下,会发现 jdk1.8.0_60 目录,表示add命令还执行了解压命令,如下图所示:

                                                            

      b.COPY命令,我们定义一个Dockerfile, 代码如下:

    FROM centos
    MAINTAINER  zhengjingmao@163.com
    RUN mkdir /datas
    ADD jdk-8u60-linux-x64.tar.gz /datas/
    WORKDIR /datas/
    CMD ["/bin/bash"]

           执行命令:docker build -t mycentos .  构建mycentos镜像。

        然后启动容器,进入到 /datas/目录下,会看到jdk-8u60-linux-x64.tar.gz文件,并没有解压,如下图所示:

                                                           

       c.ENV命令,配置环境变量,我们还是用上面提到的jdk为例,做过Java开发的朋友都知道,jdk需要配置环境变量,Dockerfile的内容如下所示:

    FROM centos                      
    MAINTAINER  zhengjingmao@163.com   
    RUN mkdir -p /datas/ 
    ADD jdk-8u60-linux-x64.tar.gz /datas/
    ENV JAVA_HOME=/datas/jdk1.8.0_60                    #配置JAVA_HOME
    ENV PATH=$JAVA_HOME/bin:$PATH                       #配置PATH
    CMD ["/bin/bash"]

                因为内容的重复性,在这里就不赘述了。当我们容器启动后,我们输入:java  -version命令,就能看到我们熟悉的内容了。

       d.CMD关键字,在镜像构建阶段不执行,在容器启动阶段执行(而我们的RUN关键字定义的指令在容器构建阶段就会执行,请记住它与CMD的区别)。如果一个Dockerfile中有多个CMD命令,后面的会覆盖前面的,说白了只有最后一个生效,如下代码和注释:

    ............省略............
    CMD echo "<<<<<<<<<<<nice to meet you>>>>>>>>>>"
    CMD /bin/bash
    CMD echo "==========How are you?============="    #当容器启动的时候只有该行代码会执行,会将前两行代码覆盖

          CMD还有一个问题,就是当我们使用 docker run命令的时候,我们可以在整个docker命令的最后加上其他额外的命令,那么额外的命令会覆盖Dockerfile中所有的CMD命令,例如我们执行如下命令:docker run -it centos ls / -l,最终的结果如下图所示:  

                                                            

           e. ENTRYPOINT指令,和CMD命令差不多,如果一个Dockerfile中有多个ENTRYPOINT,只有最后一个生效。但是他们还是有区别的,如果ENTRYPOINT后面有CMD,当以exec的方式运行的时候,CMD的值会作为参数给ENTRYPOINT,可能很多人看到这句话不大理解,那么我们来两个例子:

      例一:  

    FROM centos                      
    MAINTAINER  zhengjingmao@163.com   
    RUN mkdir -p /datas/ 
    ENTRYPOINT ["echo", "hello"]
    CMD ["world"]                           #会将world作为echo hello的参数,最后的命令其实为echo hello world 

                                                            

      例二:

    FROM centos                      
    MAINTAINER  zhengjingmao@163.com   
    RUN mkdir -p /datas/ 
    ENTRYPOINT ["echo", "hello"]

                                                           

      总结:当我们理解了CMD和ENTRYPOINT两个命令的区别后,以后在使用的过程中就不会出现各种问题了。

  • 相关阅读:
    继承Runnable 实现Synchronized 同步锁
    SSM框架整合(IntelliJ IDEA + maven + Spring + SpringMVC + MyBatis)
    Nginx采用yum安装-Carr
    SpringBoot idea maven打包war及运行war包
    根据现有PDF模板填充信息(SpringBoot)
    java后台简单从腾讯云下载文件通知前端以附件的形式保存
    java后台简单从阿里云上传下载文件并通知前端以附件的形式保存
    Security-OAuth2.0 密码模式之客户端实现
    Security-OAuth2.0 密码模式之服务端实现
    Redis-Java 交互的应用
  • 原文地址:https://www.cnblogs.com/miller-zou/p/11111756.html
Copyright © 2011-2022 走看看