• Docker系列-第六篇DockerFile解析


    1.手动编写一个dockerfile文件,当然必须要符合file的规则

    2.有了这个文件,直接docker build命令执行,获得一个自定义的镜像

    3.run

    1.是什么

    Dockerfle 是一个文本格式的配置文件, 用户可以使用 Dockerfle 来快速创建自定义的镜像。

    Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

    1.1三步骤

    • 编写Dockerfile文件
    • docker build
    • docker run

    2.DockerFile构建过程解析

    2.1Dockerfile内容基础知识

    1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数

    2:指令按照从上到下,顺序执行

    3:#表示注释

    4:每条指令都会创建一个新的镜像层,并对镜像进行提交

    2.2Docker执行Dockerfile的大致流程

    (1)docker从基础镜像运行一个容器

    (2)执行一条指令并对容器作出修改

    (3)执行类似docker commit的操作提交一个新的镜像层

    (4)docker再基于刚提交的镜像运行一个新容器

    (5)执行dockerfile中的下一条指令直到所有指令都执行完成

    2.3小总结

    从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

    • Dockerfile是软件的原材料
    • Docker镜像是软件的交付品
    • Docker容器则可以认为是软件的运行态。
      Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

    在这里插入图片描述
    1、Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

    2、Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;

    3、Docker容器,容器是直接提供服务的。

    3.DockerFile体系结构(保留字指令)

    3.1FROM

    基础镜像,当前新镜像是基于哪个镜像的

    每个Dockerfile的第一挑指令必须是FROM,FROM指令指定一个已存在的镜像,后续指令都继续该镜像进行,这个镜像也称为基础镜像

    3.2MAINTAINER

    MAINTAINER指令没有具体的格式,建议一般使用姓名和邮箱

    3.3RUN

    镜像构建时需要运行的命令(即镜像制作过程中需要执行的命令)

    每条RUN指令都会创建一个新的镜像层,如果该指令执行成功,就会将此镜像层提交。

    如果需要执行多条命令,可使用多行RUN命令,但经验告我,将多条指定通过命令换行合并成一条,这样将减少锁构建的体积。原因,上面也已经说了,在镜像中每执行一条命令,都会形成新的镜像层,需要尽可能的较少镜像层,从而减少镜像的提示

    3.4EXPOSE

    当前容器对外暴露出的端口

    3.5WORKDIR

    指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点

    可以用过-w标志在运行时覆盖工作目录

    3.6ENV

    用来在构建镜像过程中设置环境变量

    ENV MY_PATH /usr/mytest
    这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
    也可以在其它指令中直接使用这些环境变量,

    比如:WORKDIR $MY_PATH

    3.7ADD

    将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包

    在ADD文件时,Docker通过目的地址参数末尾的字符来判断文件源是目录还是文件。如果目标地址以/结尾那么Docker就认为源位置指向的是一个目录。如果目的地址不是以/结尾,那么Docker就认为原文件指向的是文件。

    ADD jdk-8u91-linux-x64.tar.gz /opt

    是将宿主机当前目录下的 jdk-8u91-linux-x64.tar.gz 拷贝到容器/opt目录下 ,容器的目标路径必须的绝对路径。

    一般将Dockerfile与需要添加到容器中的文件放在同一目录下,有助于编写来源路径

    3.8COPY

    类似ADD,拷贝文件和目录到镜像中。没有自动解压的功能
    将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置

    3.9VOLUME

    容器数据卷,用于数据保存和持久化工作

    3.10CMD

    指定一个容器启动时要运行的命令

    ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数

    CMD指令用于执行容器提供默认值。每个Dockerfile只有一个CMD命令,如果指定了多个CMD命令,那么只有最后一个会被执行。

    Docker run 命令可以覆盖CMD指令。如果在Dockerfile里指定了CMD指令,而同时在docker run命令行中也指定的要运行的命令,命令行中指定的命令会覆盖Dockerfile中的CMD指令。

    如 CMD java app.jar 容器启动时启动app.jar应用

    3.11ENTRYPOINT

    指定一个容器启动时要运行的命令

    ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数

    区别:

    可以在docker run 命令中覆盖CMD命令。

    ENTRYPOINT指令提供的命令则不容易在启动容器时被覆盖。实际上docker run命令中指定的任何参数会被当做参数再次传递给ENTRYPOINT指令中指定的命令。

    3.12ONBUILD

    当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发

    3.13USER

    指定该镜像会以什么用户运行

    3.13小结

    在这里插入图片描述

    4.案例

    使用Dockerfile构建Java镜像入门1

    • step 1

      新建Dockerfile文件

      touch Dokcerfile
      
    • step 2

      编写Dockerfile脚本

      FROM centos:latest
      MAINTAINER "NIU GANG"<863263957@qq.com>
      # 在opt目录下新建apps目录
      RUN  mkdir -p /opt/apps
      # 在当前目录下及和Dockerfile在一个目录下,将jdk安装包增加到镜像的opt/apps目录下
      # ADD目录会自动将 .tar.gz包进行解压
      ADD jdk-8u211-linux-x64.tar.gz /opt/apps
      # 在启动容器是执行命令
      CMD /opt/apps/jdk1.8.0_211/bin/java -version
      
    • step 3 构建镜像

      [root@localhost tools]# docker build -t niugang/java .
      Sending build context to Docker daemon  197.8MB
      Step 1/5 : FROM centos:latest
       ---> 9f38484d220f
      Step 2/5 : MAINTAINER "NIU GANG"<863263957@qq.com>
       ---> Running in e4a4a0c1ffa9
      Removing intermediate container e4a4a0c1ffa9
       ---> a7f400aae1a7
      Step 3/5 : RUN  mkdir -p /opt/apps
       ---> Running in 49f2c1f076c0
      Removing intermediate container 49f2c1f076c0
       ---> 287c44707477
      Step 4/5 : ADD jdk-8u211-linux-x64.tar.gz /opt/apps
       ---> cf2dfbb373c8
      Step 5/5 : CMD /opt/apps/jdk1.8.0_211/bin/java -version
       ---> Running in 83d41700285a
      Removing intermediate container 83d41700285a
       ---> 79bf24642eb4
      Successfully built 79bf24642eb4
      Successfully tagged niugang/java:latest
      

    对于 docker build -t niugang/java . 这个命令

    -t 选项指定镜像名称 并读取当前(即.)目录中的Dockerfile文件

    • step 4 验证

      [root@localhost tools]# docker run --rm niugang/java
      java version "1.8.0_211"
      Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
      Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
      

      --rm 是启动并删除容器

      注意:

      最开始在启动docker run --rm niugang/java 会报

      /bin/sh: /opt/apps/jdk-8u211/bin/java: No such file or directory

      是因为当初认为ADD 增加 jdk-8u211-linux-x64.tar.gz 后解压的名称叫 jdk-8u211(感觉犯例了一个常识性的错误),但其实解压完成后的文件夹名称为1.8.0_211

    使用Dockerfile构建Java镜像入门2

    一般在安装JDK后需要设置JAVA_HOME 与PATH 这样就可以直接在命令中使用Java命令了,而须带路径参数

    使用Dockerfile中的ENV指令来设置所需的环境变量

    前提:

    为了二次生成的镜像于之前的不重名,修改之前生成镜像的tag

    docker tag 79bf24642eb4 niugang/java:1.0
    

    修改之前的Dockerfile文件,修改后的文件内容如下

    FROM centos:latest
    MAINTAINER "NIU GANG"<863263957@qq.com>
    RUN  mkdir -p /opt/apps
    ADD jdk-8u211-linux-x64.tar.gz /opt/apps
    ENV JAVA_HOME /opt/apps/jdk1.8.0_211
    ENV PATH $JAVA_HOME/bin:$PATH
    CMD java -version
    

    重新构建镜像

    [root@localhost tools]# docker build -t niugang/java .
    Sending build context to Docker daemon  197.8MB
    Step 1/7 : FROM centos:latest
     ---> 9f38484d220f
    Step 2/7 : MAINTAINER "NIU GANG"<863263957@qq.com>
     ---> Using cache
     ---> a7f400aae1a7
    Step 3/7 : RUN  mkdir -p /opt/apps
     ---> Using cache
     ---> 287c44707477
    Step 4/7 : ADD jdk-8u211-linux-x64.tar.gz /opt/apps
     ---> Using cache
     ---> cf2dfbb373c8
    Step 5/7 : ENV JAVA_HOME /opt/apps/jdk1.8.0_211
     ---> Running in 6117528026ae
    Removing intermediate container 6117528026ae
     ---> 1b9e9c656a8e
    Step 6/7 : ENV PATH $JAVA_HOME/bin:$PATH
     ---> Running in 5711715ae4eb
    Removing intermediate container 5711715ae4eb
     ---> 82f94b6f5211
    Step 7/7 : CMD java -version
     ---> Running in fcb8b117a0c2
    Removing intermediate container fcb8b117a0c2
     ---> 9a26c48936a4
    Successfully built 9a26c48936a4
    Successfully tagged niugang/java:latest
    

    通过上面输出的信息可以观察到,step2 step3 step4 这三个步骤直接从缓存中获取之前构建的镜像,而不是重新构建镜像

    Dockerfile和构建和缓存

    由于每一步的构建都会将结果提交未镜像,所以Docker的构建过程就显得非常聪明。它会将之前的镜像层看作缓存。

    要想忽略缓存功能,可以使用docker build --no-cache标志

    如 docker build --no-cache -t niugang/java .

    自定义mycentos镜像

    • 新建Dockerfile

      touch Dockerfile
      
    • 编写Dockerfile

      FROM centos
      MAINTAINER ng<863263957@qq.com>
       
      ENV MYPATH /usr/local
      WORKDIR $MYPATH
       
      RUN yum -y install vim
      RUN yum -y install net-tools
       
      EXPOSE 80
       
      CMD echo $MYPATH
      CMD echo "success--------------ok"
      CMD /bin/bash
      
    • 构建

      docker build -t 新镜像名:TAG .

      参数:

      -f :指定要使用的Dockerfile路径;

      --no-cache :创建镜像的过程不使用缓存;

      -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;

    • 运行

    ​ docker run -it 新镜像名:TAG

    • 列出镜像变更历史

    ​ docker history 镜像ID

    CMD/ENTRYPOINT案例镜像

    共同特点:都是指定一个容器启动时要运行的命令

    CMD

    Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换

    列如:

    以下是运行tomcat镜像的命令

    docker run -it -p 8888:8080 tomcat

    从docker.hub上查看tomcat镜像的Dockerfile文件会发现最后有 CMD ["catalina.sh", "run"]

    现在以如下方式启动:

    ENV CATALINA_HOME /usr/local/tomcat
    ENV PATH (CATALINA_HOME/bin:)PATH
    RUN mkdir -p "$CATALINA_HOME"
    WORKDIR $CATALINA_HOME

    在tomcat的Dockerfile中设置的WORKDIR为/usr/local/tomcat

    docker run -it -p 8888:8080 tomcat ls -l

    [root@localhost mycmdip]# docker run -it -p 8888:8080 tomcat ls -l
    total 124
    -rw-r--r--. 1 root root  19534 Jul  4 20:56 BUILDING.txt
    -rw-r--r--. 1 root root   5407 Jul  4 20:56 CONTRIBUTING.md
    -rw-r--r--. 1 root root  57011 Jul  4 20:56 LICENSE
    -rw-r--r--. 1 root root   1726 Jul  4 20:56 NOTICE
    -rw-r--r--. 1 root root   3255 Jul  4 20:56 README.md
    -rw-r--r--. 1 root root   7139 Jul  4 20:56 RELEASE-NOTES
    -rw-r--r--. 1 root root  16262 Jul  4 20:56 RUNNING.txt
    drwxr-xr-x. 2 root root   4096 Jul 18 02:55 bin
    drwxr-sr-x. 2 root root    238 Jul  4 20:56 conf
    drwxr-sr-x. 2 root staff    78 Jul 18 02:55 include
    drwxr-xr-x. 2 root root   4096 Jul 18 02:54 lib
    drwxrwxrwx. 2 root root      6 Jul  4 20:53 logs
    drwxr-sr-x. 3 root staff   151 Jul 18 02:55 native-jni-lib
    drwxr-xr-x. 2 root root     30 Jul 18 02:54 temp
    drwxr-xr-x. 7 root root     81 Jul  4 20:53 webapps
    drwxrwxrwx. 2 root root      6 Jul  4 20:53 work
    

    以上说明:

    ls -l 命令覆盖了Dockerfile中的catalina.sh run

    NETRYPOINT

    docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合

    通过案列镜像对比

    操作 1

    执行CMD版查询IP信息的镜像

    具体Dockerfile文件内容为:

    FROM centos
    RUN yum install -y curl
    CMD [ "curl", "-s", "http://ip.cn" ]
    

    构建镜像

    运行镜像 会返回你当前的ip信息

    问题:如果我们希望显示 HTTP 头信息,就需要加上 -i 参数
    在这里插入图片描述

    为什么会出错:

    我们可以看到可执行文件找不到的报错,executable file not found。

    之前也提到过跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。

    因此这里的 -i CMD而不是添加在原来的后面。而根本不是命令,所以自然找不到

    操作2

    制作ENTROYPOINT版查询IP信息的容器

    具体Dockerfile文件内容为:

    FROM centos
    RUN yum install -y curl
    ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
    

    这样制作出的镜像在运行过程就不会报错了 ,就会显示出http头信息了

    自定义tomcat9镜像

    step1 在根目录下新建mytomcat9文件夹

    mkdir mytomcat9
    

    step2 上传jdk tomcat安装包

    step3 新建Dockerfile文件

    touch Dockerfile
    

    step4 编写Dockerfile 内容如下

    FROM         centos
    MAINTAINER    niugang<863263957@qq.com>
    #把宿主机当前上下文的test.txt拷贝到容器/usr/local/路径下并重命名为test1.txt
    COPY test.txt /usr/local/test1.txt
    #把java与tomcat添加到容器中
    ADD jdk-8u211-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.27.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_211
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.27
    ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.27
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    #容器运行时监听的端口
    EXPOSE  8080
    #启动时运行tomcat
    # ENTRYPOINT ["/usr/local/apache-tomcat-9.0.27/bin/startup.sh" ]
    # CMD ["/usr/local/apache-tomcat-9.0.27/bin/catalina.sh","run"]
    CMD /usr/local/apache-tomcat-9.0.27/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.27/bin/logs/catalina.out
    

    step5 构建镜像

    docker build -t niugang/tomcat9 .
    

    step6 运行容器

    docker run -d -p 9080:8080 --name myt9  -v /mytomcat9/mywebapp/:/usr/local/apache-tomcat-9.0.27/webapps   -v /mytomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.27/logs niugang/tomcat9 --privileged=true
    

    上述运行容器创建两个数据卷

    第一个是将容器中的tomcat日志映射到宿主机上
    第二个是 将tomcat中的webapps目录映射到宿主机上方便日后发布应用
    也可以将容器中tomcat的配置conf文件夹映射到宿主机

    step7 验证应用发布

    在映射的/mytomcat9/mywebapp/ 新建test目录,test目录下新建index.html,写入helle world。

    [root@localhost test]# pwd
    /mytomcat9/mywebapp/test
    [root@localhost test]# ll
    总用量 4
    -rw-r--r--. 1 root root 12 10月 23 21:30 index.html
    

    在这里插入图片描述

    5.小总结

    微信公众号
    JAVA程序猿成长之路

  • 相关阅读:
    危机下,你还敢提加薪吗?
    大白兔奶糖三聚氰胺事件后21日起重新上架
    15个nosql数据库
    向网页设计师推荐15个很棒的网站
    腾讯新浪通过IP地址获取当前地理位置(省份)的接口
    5个最顶级jQuery图表类库插件Charting plugin
    12种JavaScript MVC框架之比较
    企业网站设计的启示
    游戏引擎大全
    推荐几份能够帮助你学习 CSS3 的实用帮助手册
  • 原文地址:https://www.cnblogs.com/niugang0920/p/12187068.html
Copyright © 2020-2023  润新知