• Dockerfile编写的注意事项


    一.Dockerfile合理分层

    Dockerfile的写法不合理,有时候会导致镜像膨胀,由于Docker是分层设计,而在Dockerfile中,每一条指令都拥有自己的context,而执行到下一条指令时,则会将下一层的构建层叠加到上一层上。因此,假如你在上一层指令做了一些包下载操作安装操作,然后在下一层再做清理,其实没什么用,只能说明你下一层引入的diff是0而已。

    可以实验一下:

    对照组A:下载清理操作全在同一层

    FROM centos
    MAINTAINER **
    
    RUN yum -y update
    RUN yum -y install wget
    
    RUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-x64.tar.gz" -O /tmp/jdk8_x64.tar.gz && gunzip /tmp/jdk8_x64.tar.gz && tar -C /opt -xf /tmp/jdk8_x64.tar && ln -s /opt/jdk1.8.0_121 /opt/jdk && yum clean all && rm -fr /tmp/*

    对照组B:下载清理操作放在不同层

    FROM centos
    MAINTAINER **
    
    RUN yum -y update
    RUN yum -y install wget
    
    RUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-x64.tar.gz" -O /tmp/jdk8_x64.tar.gz && gunzip /tmp/jdk8_x64.tar.gz && tar -C /opt -xf /tmp/jdk8_x64.tar && ln -s /opt/jdk1.8.0_121 /opt/jdk 
    RUN yum clean all 
    RUN rm -fr /tmp/*

    分别执行构建操作,得到的镜像差异很大,其中test1为对照组A的构建结果,test2为对照组B的构建结果,两者相差400M.

    alex@ubuntu:~/workspace/docker_project$ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    test2               latest              a65c6cced43b        13 minutes ago      1.1 GB
    test1               latest              67897397b053        14 minutes ago      729 MB

     二.CMD跟ENTRYPOINT的合理使用

    举个例子,假设你需要容器启动时,去执行一个后台常驻脚本,那我们一般想到的是在CMD中执行脚本即可。

    假设对照组A的Dockerfile:

    FROM centos
    MAINTAINER **
    
    EXPOSE 8000
    WORKDIR /
    
    CMD [ "/bin/bash","-c","/usr/bin/python2.7 -m SimpleHTTPServer" ]

    那正常镜像构建成功后,启动容器

    alex@ubuntu:~/test$ docker build -t test1 .
    Sending build context to Docker daemon 2.048 kB
    Step 1/5 : FROM centos
     ---> 98d35105a391
    Step 2/5 : MAINTAINER shufeng, shufeng.lsf@alibaba-inc.com
     ---> Using cache
     ---> 054ed64f1b34
    Step 3/5 : EXPOSE 8000
     ---> Running in e706b62c3c16
     ---> f1fd512940dc
    Removing intermediate container e706b62c3c16
    Step 4/5 : WORKDIR /
     ---> daa58d7899df
    Removing intermediate container 5c51961e6e87
    Step 5/5 : CMD /bin/bash -c /usr/bin/python2.7 -m SimpleHTTPServer
     ---> Running in 5dfa9742ccaf
     ---> 6ff71edb9bad
    Removing intermediate container 5dfa9742ccaf
    Successfully built 6ff71edb9bad

    启动容器:

    alex@ubuntu:~/test$ docker run -it -d -p 8001:8000 6ff71edb9bad
    a4318a775ec005473f6bc9342cd3c14b55981b334cc6160e7ea17e802f6eff15

    查看一下映射情况

    可以发现映射成功了。但这样启动有适合什么情况呢,只适合后台启动的情况,让我们试试另一种启动容器的方式

    alex@ubuntu:~/test$ docker run -it -d -p 8001:8000 6ff71edb9bad /bin/bash
    0fdaf33f00fb9307394e4b91577af026627801ab6364ef6729aaf9754eb84455
    alex@ubuntu:~/test$ 
    alex@ubuntu:~/test$ telnet 127.0.0.1 8001
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    Connection closed by foreign host.

    可以发现当我需要在容器启动后进入命令行时,/bin/bash的操作直接将CMD的指令覆盖了。因此,这时候需要用ENTRYPOINT来代替CMD,对应的Dockerfile如下。

    FROM centos
    MAINTAINER **
    
    EXPOSE 8000
    WORKDIR /
    ENTRYPOINT ["/bin/bash","-c","/usr/bin/python2.7 -m SimpleHTTPServer"]

    在这里说下CMD跟ENTRYPOINT的区别。

    docker run命令行可以覆盖CMD指令,而ENTRYPOINT则不会,此外,可以通过docker run在命令行中指定的参数,来传递给ENTRYPOINT指令中指定的命令,这样就可以达到动态执行的效果。

  • 相关阅读:
    JDK集合框架--LinkedList
    JDK集合框架--ArrayList
    JDK集合框架--综述
    JDK常用类解读--StringBuffer、StringBuilder
    JDK常用类解读--String
    【spring 注解驱动开发】扩展原理
    【spring 注解驱动开发】spring事务处理原理
    【spring 注解驱动开发】Spring AOP原理
    【spring 注解驱动开发】spring自动装配
    【spring 注解驱动开发】spring对象的生命周期
  • 原文地址:https://www.cnblogs.com/alexkn/p/6658642.html
Copyright © 2020-2023  润新知