首页 > 技术文章 > DockerFile解析[5]

dong320 2020-10-31 23:48 原文

是什么

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

构建三步骤

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

文件什么样??

Centos:

https://hub.docker.com/_/centos

https://github.com/CentOS/sig-cloud-instance-images/blob/12a4f1c0d78e257ce3d33fe89092eee07e6574da/docker/Dockerfile

scratch是所有镜像的祖先,类似于 java的Object

FROM scratch
ADD centos-8-x86_64.tar.xz /
LABEL org.label-schema.schema-version="1.0"     org.label-schema.name="CentOS Base Image"     org.label-schema.vendor="CentOS"     org.label-schema.license="GPLv2"     org.label-schema.build-date="20200809"
CMD ["/bin/bash"]

 

tomcat:

https://hub.docker.com/_/tomcat

https://github.com/docker-library/tomcat/blob/300ac03f4696c761a81fa10afbb893f3368061de/8.5/jdk8/openjdk-buster/Dockerfile

FROM openjdk:8-jdk-buster

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

# let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
...此处省略中间代码
RUN set -eux; \
    \
    savedAptMark="$(apt-mark showmanual)"; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        gnupg dirmngr \
        wget ca-certificates \
    ; \
...
...此处省略中间代码
...

EXPOSE 8080
CMD ["catalina.sh", "run"]

 

DockerFile构建过程解析

 

Dockerfile内容基础知识

  • 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  • 指令按照从上到下,顺序执行
  • #表示注释
  • 每条指令都会创建一个新的镜像层,并对镜像进行提交

 

Docker执行Dockerfile的大致流程

  • docker基础镜像运行一个容器
  • 执行一条指令并对容器作出修改
  • 执行类似docker commit的操作提交一个新的镜像层
  • docker再基于刚提交的镜像运行一个新容器
  • 执行dockerfile中的下一条指令直到所有指令都执行完成

 

小总结:

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

  • Dockerfile是软件的原材料、制作步骤
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

 

保留字指令

 

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

MAINTAINER 镜像维护者的姓名和邮箱地址

RUN
容器构建时需要运行的命令
EXPOSE 当前容器对外暴露出的端口
WORKDIR 指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点
ENV 用来在构建过程中设置环境变量 // 查下作用范围
ADD 将宿主机目录下的文件拷贝进镜像,且ADD命令会自动处理URL和解压tar压缩包
COPY 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径>的文件/目录复制到新的一层镜像内的<目标路径>位置
    COPY src dest     COPY ["src" "dest"]
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 它主要作用是默认的容器启动执行命令    Dockerfile中可以有多个CMD指令,但只有最后一个生效,如果我们在docker run时指定了命令或者Dockerfile中有ENTRYPOINT,那么CMD就会被覆盖。    CMD 指令的三种用法:      shell格式: CMD <命令> 参数1 参数2 如:CMD echo "hello cmd!" 命令command默认是在"/bin/sh -c"下执行      exec格式: CMD ["可执行文件", "参数1", "参数2" ...] 如:CMD ["/bin/bash", "-c", "echo 'hello cmd!'"] // 官网推荐写法
     参数列表格式:
CMD ["参数1", "参数2" ...],在指定了ENTRYPOINT指令后,用CMD指定具体的参数。

ENTRYPOINT 指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数。
   ENTRYPOINT才是正统地用于定义容器启动以后的执行体的,其实我们从名字也可以理解,这个是容器的“入口”。
   ENTRYPOINT两种用法:
     shell格式: ENTRYPOINT ["executable", "param1", "param2"] // 官网推荐写法
            如:CMD ["p in cmd"]
              ENTRYPOINT ["echo"]

     exec格式:ENTRYPOINT command param1 param2 // 在这种模式下,任何run和cmd的参数都无法被传入到entrypoint里
           如:CMD ["p in cmd"]
             ENTRYPOINT echo

     如果docker run命令后面有东西,那么后面的全部都会作为entrypoint的参数。如果run后面没有额外的东西,但是cmd有,那么cmd的全部内容会作为entrypoint的参数,这同时是cmd的第二种用法。
     这也是网上说的entrypoint不会被覆盖。当然如果要在docker run里面覆盖,也是有办法的,使用--entrypoint即可。

     具体区别可参考: CMD与ENTRYPOINT的区别
   CMD 命令可以被替代;ENTRYPOINT 可以追加命令
   总结下一般该怎么使用:
   一般还是会用ENTRYPOINT的中括号形式作为docker容器启动以后的默认执行命令,里面放的是不变的部分,可变部分比如命令参数可以使用CMD的形式提供默认版本,也就是docker run里面没有任何参数时使用的默认参数。
   如果我们想用默认参数,就直接run,否则想用其他参数,就run里面加参数。

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


 

推荐阅读