Docker学习第三课 -- Dockerfile详解

一、 什么是dockerfile?

     Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。

docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。

      在Docker中创建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件,我们可以理解成火箭发射的A、B、C、D…的步骤。Dockerfile其内部包含了一条条的指令每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建

                 

Dockerfile结构大致分为四个部分:

  (1)基础镜像信息

  (2)维护者信息

  (3)镜像操作指令

  (4)容器启动时执行指令。

二、环境介绍

  • 1.Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下,可以为Dockerfile父目录的子目录
  • 2.Dockerfile中相对路径默认都是Dockerfile所在的目录
  • 3.Dockerfile中一定要惜字如金,能写到一行的指令,一定要写到一行,原因是分层构建,联合挂载这个特性。
  • Dockerfile中每一条指令被视为一层
  • 4.Dockerfile中指明大写(约定俗成)

三、Dockerfile指令

    Dockerfile中包括FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD等13个指令。

指令解释
FROM指定基础镜像,即当前镜像是基于哪个镜像的并且必须是第一条指令
MAINTAINER指明该镜像的作者和其电子邮件
RUN指定构建过程中要执行的命令
ENV设置环境变量
WORKDIR指定默认的工作目录,即进入容器后默认进入的目录
COPY拷贝文件或者目录到镜像中
ADD拷贝文件到镜像中,且会自动解压缩,可以访问网络资源,类似wget
EXPOSE指定对外暴露的端口
VOLUME创建挂载点,也成容器数据卷,用于数据共享和持久化
CMD副本创建容器后,容器启动的时候要执行是命令
ENTRYPOINT启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
USER指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户

    

四 指令介绍

  4.1 FROM:指定基础镜像,必须为第一个命令

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest> 
三种写法,其中<tag>和<digest> 是可选项,如果没有选择,那么默认值为latest

示例:
  FROM centos

 4.2 MAINTAINER 维护者信息

格式:
    MAINTAINER <name>
示例:
    MAINTAINER dukun ai
    MAINTAINER xxxx@163.com
    MAINTAINER dukun ai <xxxxx@163.com>

4.3 LABEL  为镜像指定标签

LABEL <key>=<value> <key>=<value> <key>=<value> ...
 一个Dockerfile种可以有多个LABEL,如下:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
 但是并不建议这样写,最好就写成一行,如太长需要换行的话则使用\符号

如下:

LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
 

说明:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖

4.4 RUN 构建镜像的时候执行命令

RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行
格式:
    RUN <command>
exec执行
格式:
    RUN ["executable", "param1", "param2"]
示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
注:
  RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。
如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

  注:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错,RUN书写时的换行符是\

4.5 ADD:将本地文件添加到容器中

      拷贝文件、文件必须和Dockerfil在同一目录  tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

格式:
    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
示例:
    ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/

4.6 COPY 

    功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

4.7 ENV 配置环境变量

在其他指令中可以直接引用ENV设置的环境变量。

格式:
    ENV <key> <value>  #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
    ENV <key>=<value> ...  #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,
如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH .:$JAVA_HOME/lib
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.30
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

4.8 EXPOSE 声明容器运行的服务端口

      EXPOSE命名适用于设置容器对外映射的容器端口号,如tomcat容器内使用的端口8080,则用EXPOSE命令可以告诉外界该容器的8080端口对外

格式:
    EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080
    EXPOSE 11211/tcp 11211/udp
注:
  EXPOSE并不会让容器的端口访问到主机。要使其可访问,
    需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

4.9 WORKDIR:工作目录,类似于cd命令

      通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY
等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

格式:
    WORKDIR /path/to/workdir
示例:
    WORKDIR /a  (这时工作目录为/a)
    WORKDIR b  (这时工作目录为/a/b)
    WORKDIR c  (这时工作目录为/a/b/c)

  

4.10 CMD  容器启动的时候执行

      CMD命令用于容器启动时需要执行的命令,CMD在Dockerfile中只能出现一次,如果出现多个,那么只有最后一个会有效。
其作用是在启动容器的时候提供一个默认的命令项。

      如果用户执行docker run的时候提供了命令项,就会覆盖掉这个命令,没提供就会使用构建时的命令。

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
   如容器启动时进入bash:
   CMD /bin/bash
   CMD ["/bin/bash"]
注:
   CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

4.11 ENTRYPOINT  容器启动执行命令

  ENTRYPOINT的作用和用法和CMD一模一样,但是ENTRYPOINT有和CMD有2处不一样:

  1. CMD的命令会被docker run的命令覆盖而ENTRYPOINT不会
  2. CMD和ENTRYPOINT都存在时,CMD的指令变成了ENTRYPOINT的参数,并且此CMD提供的参数会被 docker run 后面的命令覆盖
用例一:使用CMD要在运行时重新写命令才能追加运行参数,ENTRYPOINT则可以运行时接受新参数。
示例:
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

追加-i参数
$ docker run myip -i
......

4.12 VOLUME 容器目录挂载点

    VOLUME用来创建一个可以从本地主机或其他容器挂载的挂载点。例如我们知道tomcat的webapps目录是放web应用程序代码的地方,此时我们要把webapps目录挂载为匿名卷,这样任何写入webapps中的心都不会被记录到容器的存储层,让容器存储层无状态化。
格式:
    VOLUME ["/path/to/dir"]
示例:
    VOLUME ["/data"]
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"

4.13 USER

设置启动容器的用户,可以是用户名或UID,所以,只有下面的两种写法是正确的

格式:
  USER user
  USER user:group
  USER uid
  USER uid:gid
  USER user:gid
  USER uid:group
 示例:
      USER www
 注:
  使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。
镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

使用这个命令一定要确认容器中拥有这个用户,并且拥有足够权限
 

4.14 ONBUILD:用于设置镜像触发器

   ONBUILD用于配置当前所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。
意思就是:这个镜像创建后,如果其它镜像以这个镜像为基础,会先执行这个镜像的ONBUILD命令

格式:
  ONBUILD [INSTRUCTION]
示例:
  ONBUILD ADD . /app/src
  ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注:
  当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发

4.15 ARG

    在构建镜像时,指定一些参数,例如:

FROM centos:6
ARG user # ARG user=root
USER $user

这时,我们在docker build时可以带上自定义参数user了,如下所示:

docker build --build-arg user=edisonzhou Dockerfile .

4.16 HEALTHCHECK  健康检查

告诉Docker如何测试容器以检查它是否仍在工作,即健康检查,例如:

HEALTHCHECK --interval=5m --timeout=3s --retries=3 \
    CMD curl -f http:/localhost/ || exit 1
  其中,一些选项的说明:

 --interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒
 -- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒
 --start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒
 --retries=N (default: 3):认为检测失败几次为宕机,默认3次
  一些返回值的说明:

 0:容器成功是健康的,随时可以使用
 1:不健康的容器无法正常工作
 2:保留不使用此退出代码

4.17. docker build

     创建好Dockerfile之后,通过docker build命令来创建镜像,该命令首先会上传Dockerfile文件给Docker服务器端,服务器端将逐行执行Dockerfile中定义的指令。
    通常建议放置Dockerfile的目录为空目录。另外可以在目录下创建.dockerignore文件,让Docker忽略路径下的文件和目录,这一点与Git中的配置很相似。

通过 -t 指定镜像的标签信息,例如:docker build -t regenzm/first_image . ##"."指定的是Dockerfile所在的路径

五 示例

 5.1、自定义tomcat 镜像

#1.指定基础镜像,并且必须是第一条指令
FROM centos
#2.指明改镜像作者
MAINTAINER dukun

#3拷贝文件,文件必须与DockerFile在同一目录下
COPY dukun /usr/local
ADD jdk-8u181-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.31.tar.gz /usr/local

#4 配置环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_181

ENV CLASSPATH .:$JAVA_HOME/lib
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.31
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

# 5 配置工作路径
WORKDIR $CATALINA_HOME
#安装vim
RUN yum -y install vim
#7 设置端口
EXPOSE 8080

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

5.2 部署springboot项目

# Docker image for springboot file run
# VERSION 0.0.1
# Author: eangulee
# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER eangulee <eangulee@gmail.com>
# VOLUME 指定了临时文件目录为/tmp。
# 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp
VOLUME /tmp 
# 将jar包添加到容器中并更名为app.jar
ADD demo-0.0.1-SNAPSHOT.jar app.jar 
# 运行jar包
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar", \
"--spring.profiles.active=dev", "--server.port=8099", "> /log/app.log"]

解释下这个配置文件:

java:8是指Docker Hub上官方提供的java镜像,版本号是8也就是jdk1.8,有了这个基础镜像后,Dockerfile可以通过FROM指令直接获取它的状态——也就是在容器中java是已经安装的,接下来通过自定义的命令来运行Spring Boot应用:

VOLUME指向了一个/tmp的目录,由于Spring Boot使用内置的Tomcat容器,Tomcat默认使用/tmp作为工作目录。效果就是在主机的/var/lib/docker目录下创建了一个临时文件,并连接到容器的/tmp。

将项目的jar文件作为app.jar添加到容器

RUN表示在新创建的镜像中执行一些命令,然后把执行的结果提交到当前镜像。这里使用touch命令来改变文件的修改时间,Docker创建的所有容器文件默认状态都是“未修改”。这对于简单应用来说不需要,不过对于一些静态内容(比如:index.html)的文件就需要一个“修改时间”。

EXPOSE 容器暴露端口

ENTRYPOINT 应用启动命令 参数设定
 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值