zoukankan      html  css  js  c++  java
  • 6. Dockerfile详解

    一、Dockerfile 概念

    Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

    镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。

    Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。

    Dockfile最多不超过128层, 也就是一个docker最多128行

    1.1. Dockerfile的体系结构

    先来看一下我们最常用的centos的Dockerfile

    在hub.docker.com中所有centos

    FROM scratch
    MAINTAINER The CentOS Project <cloud-ops@centos.org>
    ADD c68-docker.tar.xz /
    LABEL name="CentOS Base Image" 
        vendor="CentOS" 
        license="GPLv2" 
        build-date="2016-06-02"
    
    # Default command
    CMD ["/bin/bash"]

    含义:

    FROM scratch
    这里引用了一个父镜像. 我们通常在使用tomcat或者jdk的时候, 他的父类镜像是centos. 而centos的父类镜像是scratch, scratch是所有镜像的基础镜像
    
    
    MAINTAINER The CentOS Project <cloud-ops@centos.org>
    MAINTAINER是备注的意思, 这是哪个团队,哪个人写的
    
    
    ADD c68-docker.tar.xz /
    这个参数后面讲解
    
    LABEL name="CentOS Base Image" 
        vendor="CentOS" 
        license="GPLv2" 
        build-date="2016-06-02"
    LABEL顾名思义,就是描述的含义
    
    
    # Default command
    CMD ["/bin/bash"]
    表示运行/bin/bash. 
    我们通常在运行docker run -it lxl/centos的时候, 有时候加/bin/bash,有时候不加. 那么什么时候加, 什么时候不加呢? 
    其实加和不加都是可以的....因为这里已经给我们自动加了/bin/bash, 如果不加就是用默认的, 如果加了, 就相当于有两个/bin/bash, 他只会执行一个

     1.2. dockerfile的编写规则

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

    2. 指令按照顺序, 从上到下, 一条指令就是一层

    3. #表示注释

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

    1.3 docker执行dockerfile的流程

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

    2. 执行一条指令并对容器修改

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

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

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

    1.4 dockerfile的保留字指令

    1. FROM: 

      基础镜像, 当前镜像是基于哪一个镜像
    2. MAINTAINER:

      镜像维护者的姓名, 邮箱地址
    3. RUN:

      容器构建时需要运行的命令
    4. EXPOSE:

      当前容器对外暴露的端口号
    5. WORKDIR:

      指定在创建容器后, 终端默认登录进来的工作目录, 一个落脚点
      没有指定, 进入到容器的根目录
    6. ENV:

      用来在构建镜像的过程中设置环境变量
      这个环境你变量可以在后续的任务Run指令中使用, 这就如同在命令前面指定了环境变量前缀一样, 也可以在其他指令中直接使用这些环境变量.

      举个例子:
      ENV MY_PATH /usr/home
      WORKDIR $MY_PATH

      这就是说, 进入到容器以后, 直接进入的工作目录不是根目录, 而是/usr/home
    7. ADD & COPY

      ADD 和 COPY一起说
      他俩都有将宿主机指定目录下的文件拷贝到到镜像中的含义.
      ADD比COPY更强大. 
      ADD有拷贝并解压的含义

      例如:
      ADD c68-docker.tar.xz /
      这个含义就是, 拷贝到根目录, 并进行解压
    8. VOLUME:

      容器数据卷, 用于数据保存和持久化
    9. CMD:

      指定一个容器启动时需要运行的命令, 
      Dockerfile中可以有多个CMD命令, 但只有最后一个生效, CMD会被docker run之后的参数替代
    10. ENTRYPOINT:

      和CMD有相同之处
      指定一个容器启动时要运行的命令
      
      ENTRYPOINT的目的和CMD一样, 都是在绑定容器启动程序及参数.
      不同之处是, ENTRYPOINT 不会被docker run后面的参数代替, 而是追加
    11. ONBUILD:

      子镜像继承自父类镜像以后, 父镜像的onbuild就会被触发, 
      这就相当于一个触发器, 满足一定条件的时候触发



     二. Dockerfile案例

    2.1 Base镜像

      Docker hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的.

      最基础的base镜像是scratch, 这是所有镜像的祖先

    2.2 案例1

    目标: 练习使用WORKDIR, FROM, EVN, RUN, CMD命令

    以centos镜像为例. 我们看

    1. 目标: 下面我们要处理的就是以上两个问题:

      1) 设置进入容器的目录不是根目录

      2) 为centos安装vim和ifconfig命令

    2. 编写dockerfile

    FROM scratch
    MAINTAINER LXL<23413@11.com
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    RUN yum -y install vim
    RUN yum -y install net-tools
    
    EXPOSE 80
    
    CMD echo "success"
    CMD /bin/bash

    下面来详细看看其含义

    基础镜像
    FROM scratch
    
    指定镜像维护的作者和邮箱
    MAINTAINER LXL<23413@11.com
    
    设置环境变量mypath
    ENV MYPATH /usr/local
    
    设置进入容器的默认目录是/usr/local
    WORKDIR $MYPATH
    
    安装vim和net-tools工具
    RUN yum -y install vim
    RUN yum -y install net-tools
    
    设置端口号是80
    EXPOSE 80
    
    运行命令,打印success
    CMD echo "success"
    
    运行命令, 进入/bin/bash
    CMD /bin/bash

    3. 构建dockerfile, 生成镜像

    docker build -f Dockerfile2 -t mycentos:1.3 .

    4. 运行构建好的镜像

    docker run -it mycentos:1.3 /bin/bash

    5. 查看dockerfile的构建历史

    docker history 镜像ID

    这个命令可以查询镜像构建的各个层

    2.3 案例2--CMD命令 和 EntryPoint的区别

    1. CMD命令

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

    查看tomcat的dockerfile. 

    .....
    最后几行
    
    RUN set -e 
        && nativeLines="$(catalina.sh configtest 2>&1)" 
        && nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" 
        && nativeLines="$(echo "$nativeLines" | sort -u)" 
        && if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then 
            echo >&2 "$nativeLines"; 
            exit 1; 
        fi
    
    EXPOSE 8080
    CMD ["catalina.sh", "run"]

    最后一行是启动tomcat的命令. 所以, 我们运行tomcat镜像的时候, 会启动tomcat

    下面, 我们在命令行中使用其他CMD命令. 按照规则, docker run中最后的参数将替换dockerfile中的参数

    docker run -it -p 8080:8080 docker.io/tomcat ls -l

    运行结果:

     没有启动tomcat,而是进入了查看当前目录的文件.

    2. ENTRYPOINT命令

    ENTRYPOINT: 执行命名, 和CMD类似, 不同的是, ENTRYPOINT命令不会被docker run中的命令替换, 而是被追加

    我们来看一个案例, curl http://ip.cn 是查询当前网络信息

    第一步: 编写一个dockerfile

    FROM docker.io/centos
    
    MAINTAINER lxl < 23242@qq.com
    
    RUN yum install -y curl
    
    CMD ["curl", "-s", "https://www.ip.cn"]

    第二步: 构建dockerfile

    docker build -f Dockerfile3 -t myip . 

      

    第三步: 运行容器

    docker run -it myip

    运行结果

    您现在的 IP:**.**.**
    所在地理位置:北京市 联通
    GeoIP: Beijing, China

    第四步: 我们还想查看header. 于是追加一个参数-i即可

    如果使用CMD就会以docker run中的命令替换dockerfile, 这时我们应该使用ENTRYPOINT.

    FROM docker.io/centos
    
    MAINTAINER lxl < 23242@qq.com
    
    RUN yum install -y curl
    
    ENTRYPOINT ["curl", "-s", "https://www.ip.cn"]

    重新build, 然后在docker run启动的时候增加 -i命令

    docker run -it myip2 -i

    1. 新建文件, 创建一个DockerFile

    文件名叫Dockerfile. 固定叫法

    文件内容如下

    From ubuntu
    MAINTAINER lxl
    CMD echo 'hello docker'

    2. 构建Dockerfile

    docker build -t demo-docker .

    domo-docker: 是生成的新的docker镜像的名字. 

    . 表示的是文件生成在当前目录

    构建的时候, 首先会判断基础镜像是否存在, 如果不存在, 则下载

    3. 查看构建好的镜像

    docker image demo-docker

     我们看到生产了一个64.2M的镜像. 版本定义了一个最新版本

    4. 运行镜像

    docker run demo-docker

     运行镜像, 打印输出hello docker

    以上我们就自己定义了一个dockerfile,并运行起来了.

    2.4 案例3--ONBUILD命令 

    第一步: 构建一个父类镜像

    FROM docker.io/centos
    MAINTAINER LXL<234@QQ.COM
    
    CMD ["/bin/bash"]
    
    增加了触发器
    ONBUILD RUN echo "onbuild starting ...... 886"

    第二步: 编译父类镜像

     docker build -f dockerfile4 -t centos03 .

    第三步: 构建一个子类镜像

    这引用的父类镜像是centos03
    FROM centos03
    MAINTAINER LXL
    <234@QQ.COM CMD ["/bin/bash"]

    第四步: 编译子类镜像

    docker build -f dockerfile5 -t child-centos04 .

     2.5 案例4

    练习COPY ADD命令

     按照如下操作执行

    1. 创建一个/docker/tomcat9文件夹, 里面放三个文件

    touch c.txt

    apache-tomcat-9.0.8.tar.gz

    jdk.tar.gz

    其中后两个文件是tomcat和jdk的压缩包, 我们提前下载好,放到文件夹里即可. 如下图所示:

    下载tomcat
    sudo curl -OL https://mirror.bit.edu.cn/apache/tomcat/tomcat-9/v9.0.35/bin/apache-tomcat-9.0.35.tar.gz
    
    
    下载jdk
    sudo curl -OL https://www.oracle.com/webapps/redirect/signon?nexturl=https://download.oracle.com/otn/java/jdk/8u251-b08/3d5a2bb8f8d4428bbe94aed7ec7ae784/jdk-8u251-linux-x64.tar.gz

    2. 在/docker/tomcat9文件夹下创建一个dockerfile文件

    FROM docker.io/centos
    
    # 设置dockerfile的作者和邮箱
    MAINTAINER lxl < 234@qq.com
    
    # 拷贝文件到指定目录并解压
    
    ADD apache-tomcat-9.0.35.tar.gz /usr/local
    ADD jdk-8u251-linux-x64.tar.gz /usr/local
    
    # 定义环境变量
    ENV WORKPATH /usr/local
    
    # 设定工作目录
    WORKDIR $WORKPATH
    
    
    # 设置jdk和tomcat的环境变量
    ENV JAVA_HOME /usr/local/jdk1.8.0_251
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35
    ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.35
    
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_BASE/bin
    
    # 设定端口号
    EXPOSE 8080
    
    # 启动并运行tomcat
    CMD $WORKPATH/apache-tomcat-9.0.35/bin/startup.sh && tail -F $WORKPATH/apache-tomcat-9.0.35/logs/catalina.out
    

    3. 构建dockerfile

    4. docker run 运行镜像

    docker run -it tomcat9

    5. 验证tomcat启动结果

    在本地输入localhost:8080. 看到tomcat启动页 

     

  • 相关阅读:
    PAT (Advanced Level) 1086. Tree Traversals Again (25)
    PAT (Advanced Level) 1085. Perfect Sequence (25)
    PAT (Advanced Level) 1084. Broken Keyboard (20)
    PAT (Advanced Level) 1083. List Grades (25)
    PAT (Advanced Level) 1082. Read Number in Chinese (25)
    HDU 4513 吉哥系列故事――完美队形II
    POJ Oulipo KMP 模板题
    POJ 3376 Finding Palindromes
    扩展KMP
    HDU 2289 Cup
  • 原文地址:https://www.cnblogs.com/ITPower/p/12677533.html
Copyright © 2011-2022 走看看