Docker 之Dockerfile详解

目录

一、Dockerfile的用法

二、一个例子 (创建tomcat镜像)

三、指令详解

(1)FROM

(2)RUN

(3)COPY

(4)ADD

(5) CMD

(6)ENTRYPOINT

(7)ENV

(8)ARG

(9)VOLUME

(10)EXPOSE

(11)WORKDIR

(12)USER

(13)HEALTHCHECK

(14)ONBUILD

(15)LABEL

四、镜像构建


一、Dockerfile的用法

Dockerfile是用来创建镜像的文件,该文件中包含构建镜像的命令。

二、一个例子 (创建tomcat镜像)

FROM ccc7a11d65b1     (这串数字是我已经创建好一个ubuntu镜像的镜像id,在这里作为tomcat的基础镜像
MAINTAINER hmk
ENV REFRESHED_AT 2018-03-10  (这个环境变量用来表名该镜像模板的最后更新时间)

#切换镜像目录,进入/usr目录
WORKDIR /usr
#在/usr/下创建jdk目录,用来存放jdk文件
RUN mkdir jdk
#在/usr/下创建tomcat目录,用来存放tomcat
RUN mkdir tomcat

#将宿主机的jdk目录下的文件拷至镜像的/usr/jdk目录下
ADD jdk1.8.0_131 /usr/jdk/
#将宿主机的tomcat目录下的文件拷至镜像的/usr/tomcat目录下
ADD apache-tomcat-7.0.81 /usr/tomcat/

#设置环境变量
ENV JAVA_HOME=/usr/jdk
ENV JRE_HOME=$JAVA_HOME/jre
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH=/sbin:$JAVA_HOME/bin:$PATH

#公开端口
EXPOSE 8080
#设置启动命令
ENTRYPOINT ["/usr/tomcat/bin/catalina.sh","run"]

三、指令详解

(1)FROM

    定制的镜像都是基于 FROM 的镜像,例如上面例子中的ccc7a11d65b1 就是定制需要的基础镜像。后续的操作都是基于 ccc7a11d65b1 (镜像)。

(2)RUN

     用于执行后面跟着的命令行命令。有以下俩种格式:   

      1、shell 格式:

RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。

      2、exec 格式:

RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

(3)COPY

     复制命令,从上下文路径中复制文件到容器的指定目录中。

(4)ADD

     ADD指令与COPY指令的功能相同,格式也相同。但在同等条件下,官方推荐使用COPY命令。ADD支持类似于tarball文件自动提取和远程URL。两者都可以修改被添加到容器的文件的所有者组/组。两者不同之处在于:

ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

注:对于以上COPY和ADD命令的一些其他的问题:

   在复制时命令如下:ADD

  1、如果镜像中没有  ,则会创建它

  2、对于所有新创建的文件/目录,其UID和GID都是0,即都是根用户。调整 可以在创建时设置 使用--chown

  3、如果文件/目录包含特殊字符,那他们需要被转义。

  4 、 可以时绝对路径,也可以是相对路径。在相对路径的情况下,其相对性根据WORKDIR指令所设置的路径来推断。

  5、如果 不是以/结尾的 那他会被视为一个文件,并且中的内容会写入到 之中。

  6、如果被指定为一个通配符模式,那么就必须是一个目录且必须以/结尾;否则,构建过程会失败。

  7、必须处于构建上下文中——它不能是构建上下文之外的目录/文件,因为docker构建过程的第一步涉及将上下文目录发送到docker守护程序。

对于ADD来说:

 如果是一个URL。而 不是一个目录并且不以反斜杠结尾,那么会从该URL中下载文件,并将文件内容写到 中。如果 是一个目录并且以反斜杠结尾,那么根据URL推断文件名,下载到/

(5) CMD

        CMD指令类似于RUN指令,用于运行程序,但二者运行的时间点不同:

        CMD在docker run 是运行    ; RUN在docker build时运行。

        作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD指令指定的程序可被docker run命令行参数中指定的要运行的程序所覆盖。

         注:如果Dockerfile中如果存在多个CMD指令,仅最后一个生效。

(6)ENTRYPOINT

         类似于CMD指令,但其不会被docker run的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数传送给ENTRYPOINT指令指定的程序。

         但是,如果允许docker run 时使用了--entrypoint选项,将覆盖CMD指令指定的程序。

         注:如果Dockerfile中如果存在多个ENTRYPOINT指令,仅最后一个生效。

(7)ENV

          设置环境变量,定义了环境变量,在后续的指令中,就可以只用这个环境变量。

(8)ARG

          构建参数,与ENV作用一致。不过作用域不一样。ARG设置的环境变量仅对Dockerfile内有效,也就是说只有在docker build 的过程中有效,构建好的镜像中不存在该环境变量。

(9)VOLUME

           定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

           作用:避免重要的数据,因容器重启而丢失,这是非常致命的。避免容器不断变大。

(10)EXPOSE

           仅仅是声明端口。

           作用:帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;在运行时使用随机端口映射时,也就是docker run -P时,会自动随机映射EXPOSE的端口。

(11)WORKDIR

            指定工作目录。用WORKDIR指定的工作目录(该目录必须是提前创建好的),会在构建镜像的每一层中都存在。

            如果dockerfile中出现多次WORKDIR,如果前一个WORKDIR指令后面使用了一个相对路径的目录,那么这个目录就是相对于之前所设置的工作目录而言的。

       如:WORKDIR /usr

              WORKDIR src

              WORKDIR app

如此命令下 最后的工作目录为:/usr/src/app

(12)USER

         用于指定后续命令的用户和用户组(用户和用户组必须提前已经存在),这边知识切换后续命令执行的用户。

(13)HEALTHCHECK

        用于指令某个程序或者指令来监控docker容器服务的运行状态。

(14)ONBUILD

       用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

(15)LABEL

      LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式。

      比如我们可以添加镜像的作者:

LABEL org.opencontainers.image.authors="chu"

四、镜像构建

1、构建

docker build -t nginx:new .

 最后一个 . 很重要  是构建上下文 可以切换成其他 比如url 等  。

2、给新建的镜像一个名字 如上已经设置过了 如果未设置。可以如下:

docker tag image_id tag_name

五、减小镜像的大小 

  • 多阶段构造

       使用多阶段构造有助于显著减少镜像大小。17.05版本之后,Docker增加了对多阶段构建的支持。多阶段镜像构建尤其适用于构建需要一些额外依赖项但运行时却不需要这些依赖项的应用程序镜像。对于典型的多阶段构造而言,构造可以有好几层。一层用于安装构建应用程序所需要的工具,一层用于生成依赖项,一层用于生成该应用程序。在最后一层中,构建阶段中送构建的应用程序会被复制到最后一层,并且只有该层会被考虑用于构建镜像,其余构建会被丢弃,以此来减少镜像大小。

  • 跳过不必要的包

      使用不必要的包以及可有可无的包会增加镜像的大小,引入不必要的依赖包,以及受攻击的范围。

  • 最小化层的数量

      对于层的数量来说,层的数量越多,镜像的大小越大,减少层的数量仍旧很重要。使用最少的命令或者合并多行单独的指令就会减少层的数量,最终减少层的数量。

  • 保持构建上下文最小化

     构建上下文中,不要将所有的文件都传入其中,尽可能保证构建上下文最小化,以减少构建时间和镜像大小。可以通过.dockerignore文件来实现。

你可能感兴趣的:(docker相关,docker,tomcat,运维)