Dockerfile详解

     Dockerfile是用来构建镜像的标准文件。在Dockerfile中按照docker官方给出的Dockerfile规范编写相应的命令,然后在运行docker build 命令就可以由用户自己构建一个docker镜像。下面对一些主要命令做出一些解释。(查看完成命令建议直接上官方网址:https://docs.docker.com/engine/reference/builder/)

FROM: 初始化一个新的构建阶段,并且为后续的指令设置一个基础镜像. 因此一个有效的Dockerfile文件必须从FROM指令开始。这个指定的镜像可以是任何有效的镜像 -- 而且通过从公共仓库拉取一个镜像是非常容器的(如果本地没有该镜像,才回去远程仓库中拉取).

RUN: 这个指令由两种形式

           1.RUN command param1,param2 ....     (command可以是任何可以在FROM指定的镜像中shell所能执行的指令)

           2. RUN ["executable","param1","param2"]

           RUN主要用来执行一些制作镜像的必要操作,比如安装相关软件,创建目录,移动文件等等。


CMD: 这个指令主要用来为一个运行的容器提供一些默认值,或者给ENTRYPOINT指令传递参数。在Dockerfile只能存在一个CMD指令,如果你指定了多条,那么会执行最后一个,忽略其他的.。CMD提供的默认值可以是一个可执行脚本,或者它也会忽略这个可执行脚本,如果你在Dockerfile中同时指定了ENTRYPOINT构建指令。


EXPOSE:  这条指令是通知docker,容器运行的时候要监听特定的网络端口。这条指令不能使这个指定被监听的端口被host宿主机访问。为了做到这点,你可以在启动容器时加上-p属性,来对外映射一些容器内部的端口,或-P 对外映射所有容器内部的端口。当然,映射到宿主机上的端口和容器内部的端口可以完全不一样。docker网络的特性支持不需在一个网络中暴露端口就可以创建网络。什么意思呢,就是说在同一个网络中的docker容器可以互相访问对方的内部的端口,而不需要暴露映射出来。(可以使用 -- link 参数来实现,在docker compose 3中,甚至不需要任何特别指定)


ENV: 环境变量设置。用于设置一些在环境变量,这样使用这个镜像启动容器后,就可以直接使用。形式为ENV <key> <value>, 或者 ENV <key>=<value>

如果要构建一个不需含有java环境的镜像时,就可以通过这个指令设置java的环境变量。


ADD:  格式为ADD <src> .. <dest> 其中src为本机的文件(夹),dest为容器内部的文件(夹).  这条指令主要用来实现将本机的一些文件复制到该镜像产生的容器中。(src指定的文件或文件夹必须和Dockerfile在同一目录,因为构建镜像时,docker会将Dockerfile所在的上下文环境全部打包发送给docker daemon)


COPY:  格式为COPY <src> .. <dest>  和ADD指令作用一样,但不支持从url中拷贝文件到容器中。


ENTRYPOINT:  指定一个在容器启动时就会执行的命令。


上面其实有一些指令的概念特别相似,因此这里有必要做些区分说明:

1.  ADD 和 COPY

ADD其实可以理解为COPY的升级版,ADD不仅支持拷贝本地文件到容器的文件系统中,还可以从指定的url路径中下载对应的文件拷贝到容器中。除此之外,两者之间几乎完全一样。因此下面重点来说说COPY指令。

COPY指令的作用前面已经介绍过,这里不在缀述。但这里有一些值得注意的地方:

NOTE:

      1. src的路径必须在当前构建镜像的上下文环境中。

      2. 如果src是一个文件夹,只会将文件夹的子文件(夹)和当前文件系统的元数据信息拷贝到容器的指定目录中,但不包括文件夹本身。

      3. 如果dest指定的目录在容器中不存在,就会自动创建相应的目录。

      4. 如果src是文件,而且dest以 / 结尾,那么src就会就会拷贝到dest/src中, 否则src文件的内容就会被写入到dest文件中。

      5. 如果src指定了多个资源文件(比如使用通配符),那么dest必须是一个目录,而且要以 / 结尾

2.CMD 和 ENTRYPOINT

CMD和ENTRYPOINT都可以指定一个容器启动时执行的命令。但CMD指定的命令或可执行脚本会被docker run 这条命令传递给容器的命令覆盖,而ENTRYPOINT则不会。

CMD有以下三种形式:

      1.CMD ["executable","param1","param2"] (exec formpreferred)

      2.CMD ["param1","param2"]

      3.CMD command param1 param2 ... (shell form)

第一种形式指定了一个可执行脚本,并将param1,param2作为参数传递给该脚本。有一点要注意,这种形式不会调用命令行解释器,这也以为着普通的shell处理不会发生。比如CMD ["echo","$HOME"] 会直接输出$HOME, 而不会对该环境变量进行替换。如果想达到变量替换的目的,可以这样:CMD ["sh","-c","echo $HOME"].在这种情况下,sh解释器(而不是docker)会做环境变量替换的工作,把$HOME替换成当前用户的家目录。当然还有一种更简单的方法,那就是直接使用第三种形式的CMD指令 : CMD echo $HOME

第二种形式主要是向ENTRYPOINT指令传递参数

第三种形式称为shell形式,它能直接在shell中运行该命令。而且它指定的command会在/bin/sh -c 中执行。

ENTRYPOINT有以下两种形式:

       1.ENTRYPOINT ["executable","param1","param2"]   (exec form preferred)

       2.ENTRYPOINT command param1,param2,..   (shell form)

ENTRYPOINT指令会在容器启动时运行,而且可以接受docker run 传递给容器的参数(或者说命令),而不会被覆盖。当然如果指定--entrypoint 也可以覆盖Dockerfile中指定的ENTRYPOINT指令。

CMD和ENTRYPOINT可以进行交互。如果Dockerfile中既有CMD又有ENTRYPOINT, 那么CMD中的命令将不会执行,而且根据两者不同的形式有一些差别,如下:



还有一些其他的指令,但上面的这些指令是使用最频繁的,通过这些指令,我们完全可以构建一些自己常用的自定义镜像。比如java镜像,tomcat镜像,canal镜像,jekens镜像等等。

最后放一份自己制作tomcat-maven-jdk集成环境镜像的Dokerfile:

FROM daocloud.io/java:8

#install maven 3.3.9
ENV MAVEN_VERSION 3.3.9
RUN mkdir -p /usr/share/maven \
  && curl -fsSL http://apache.osuosl.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz \
    | tar -xzC /usr/share/maven --strip-components=1 \
  && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
ENV MAVEN_HOME /usr/share/maven
VOLUME /root/.m2

#install tomcat 8
RUN mkdir -p /usr/share/tomcat && \
    curl -fsSL http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.16/bin/apache-tomcat-8.5.16.tar.gz | tar -xzC /usr/share/tomcat
ENV TOMCAT_HOME /usr/share/tomcat/apache-tomcat-8.5.16
EXPOSE 8080

ENTRYPOINT ${TOMCAT_HOME}/bin/startup.sh && tail -F ${TOMCAT_HOME}/logs/catalina.out

(以上技术细节皆来自docker官网,如果想要更详细地理解其他指令,请直接访问https://docs.docker.com/engine/reference/builder/)


猜你喜欢

转载自blog.csdn.net/summermangozz/article/details/77413709