zoukankan      html  css  js  c++  java
  • Docker基础内容之镜像构建

    前言

    Docker可以通过读取Dockerfile中的指令来自动构建图像。Dockerfile是一个文本文档,包含用户可以在命令行上调用的所有命令来组装一个图像。使用docker构建用户可以创建一个自动构建,该构建可以连续执行多个命令行指令。

    构建方法

    # 这里的"."代表了目录结构上下文
    docker build .

    # -f可以指定Dockerfile文件路劲,但是后面一定要用".",并且你当前的位置一定要在文件所要上传的目录位置
    docker build -f /path/Dockerfile .

    # -t 指定构建后的镜像名称
    docker build -t host-1 -f /path/Dockerfile .

    # --no-cache表示构建过程中的所产生的缓存不做保留
    docker build --no-cache .

      构建由Docker守护进程运行,而不是由CLI运行。构建流程要做的第一件事是将整个上下文(递归地)发送给守护进程。在大多数情况下,最好从一个空目录作为上下文开始,并将Dockerfile保存在该目录中。只添加构建Dockerfile所需的文件。要在构建上下文中使用文件,Dockerfile引用一条指令中指定的文件,例如一条复制指令。要提高构建的性能,可以通过在上下文目录中添加.dockerignore文件来排除文件和目录。有关如何创建.dockerignore文件的信息,请参阅此页上的文档。传统上,Dockerfile称为Dockerfile,位于上下文的根目录中。在docker build中使用-f标志指向文件系统中任何位置的Dockerfile。

    指令详解

    Dockerfile中的指令都会产生一个镜像层,哪怕你只是一个很小的声明也会产生一个镜像层。

    ARG

    ARG是docker.17版本之后出现的功能,是用来声明dockerfile所使用的变量,语法如下:

    ARG <name>[=<default value>]

    示例如下:

    ARG VERSION=latest
    FROM busybox:$VERSION
    ARG VERSION
    RUN echo $VERSION > image_version
    
    # 或者
    
    FROM busybox
    ARG user1=someuser
    ARG buildno=1

    注意:ARG变量定义从Dockerfile中定义它的行开始生效,而不是从命令行或其他地方使用参数开始。使用ENV指令定义的环境变量总是覆盖同名的ARG指令。

    FROM

    FROM指令初始化一个新的构建阶段,并为后续指令设置基本映像。因此,一个有效的Dockerfile必须从FROM指令开始。图像可以是任何有效的图像—从公共存储库中提取图像尤其容易。语法如下:

    FROM <image> [AS <name>]
    FROM <image>[:<tag>] [AS <name>]
    FROM <image>[@<digest>] [AS <name>]

    注意:FROM指令中有一个特殊镜像"scratch",表示使用空镜像,不依赖任何底层。 

    RUN

    RUN指令将在当前映像之上的新层中执行任何命令并提交结果。生成的提交映像将用于Dockerfile中的下一步。RUN指令支持两种格式,样式如下:

    RUN <command>
    RUN ["executable", "param1", "param2"]
    
    示例1
    RUN /bin/bash -c 'source $HOME/.bashrc; 
    echo $HOME'
    
    示例2
    RUN ["/bin/bash", "-c", "echo hello"]

    注意:如果使用exec执行的这种方式,括号内的参数一定要用双引号括起来

    CMD

    CMD一般用于镜像构建之后预定默认运行的指令,类似于操作系统的开机自启动,因为容器中没有开机与关机这一说,所以只能设定预定运行程序;注意CMD是默认运行指令,言外之意它与其他指令冲突的时候,它不会运行。尤其是ENTRYPOINT;语法格式如下:

    CMD ["executable","param1","param2"]
    CMD ["param1","param2"]
    CMD command param1 param2

    需要注意:当镜像运行的时候,用户手动指定了程序,则CMD里面的内容会自动失效;若Dockerfile中有ENTRYPOINT指令,则CMD会将后面的内容当成参数传递到ENTRYPOINT指令中,就是上面的第二种使用方式。

    详情请参考:https://blog.csdn.net/u010900754/article/details/78526443

    LABEL

    LABEL主要用来设置一些描述信息的标签,语法格式如下:

    LABEL <key>=<value> <key>=<value> <key>=<value> ...

    示例如下:

    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 multi.label1="value1" 
          multi.label2="value2" 
          other="value3"

    EXPOSE

    • EXPOSE指令通知Docker容器在运行时监听指定的网络端口。您可以指定端口监听TCP还是UDP,如果没有指定协议,则默认为TCP。
    • EXPOSE指令实际上并不发布端口。它作为构建映像的人员和运行容器的人员之间的一种文档类型,用于发布关于哪些端口的信息。要在运行容器时实际发布端口,请使用docker run上的-p标志发布和映射一个或多个端口,或者使用-p标志发布所有公开的端口并将它们映射到高阶端口。
    • EXPOSE默认情况下假定TCP。你也可以指定UDP:
    # 语法
    EXPOSE <port> [<port>/<protocol>...]
    
    # 示例
    EXPOSE 80/udp
    EXPOSE 80/udp

    ENV

    设定容器运行时的环境变量,语法如下:

    ENV <key> <value>
    ENV <key>=<value>

    示例如下:

    ENV myName="John Doe" myDog=Rex The Dog 
        myCat=fluffy
    
    ENV myName John Doe
    ENV myDog Rex The Dog
    ENV myCat fluffy

    ADD

    ADD指令从复制新的文件、目录或远程文件url,并将它们添加到路径的映像文件系统中。可以指定多个资源,但是如果它们是文件或目录,它们的路径将被解释为相对于构建上下文的源。语法如下:

    ADD [--chown=<user>:<group>] <src>... <dest>
    ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

    示例

    ADD ["http://pic37.nipic.com/20140113/8800276_184927469000_2.png","/opt"]

    注意:ADD添加文件到指定目录并解压,还可支持URL,但是URL仅支持web协议,不支持其他协议,例如:ftp传输协议

    COPY

    COPY指令从复制新的文件,并将它们添加到路径的映像文件系统中;COPY不会自动解压,不支持URL。语法如下:

    COPY [--chown=<user>:<group>] <src>... <dest>
    COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

    ENTRYPOINT

    ENTRYPOINT指定容器运行后必须运行的内容,ENTRYPOINT必须指定运行入口,同CMD类似,多条ENTRYPOINT只有最下面那条能够执行,语法如下:

    ENTRYPOINT ["executable", "param1", "param2"]
    ENTRYPOINT command param1 param2

    注意:ENTRYPOINT的内容也是可以在docker run的时候进行覆盖,只需要使用--entrypoint选项即可

    示例如下:

    FROM debian:stable
    RUN apt-get update && apt-get install -y --force-yes apache2
    EXPOSE 80 443
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
    ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
    
    # 或者
    FROM ubuntu
    ENTRYPOINT exec top -b

    VOLUME

    VOLUME 指令可以在镜像中创建挂载点,将镜像中的内容挂载到本地,这样只要通过该镜像创建的容器都有了挂载点。但是通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。语法如下:

    VOLUME ["/data"]

    示例如下:

    FROM ubuntu
    RUN mkdir /myvol
    RUN echo "hello world" > /myvol/greeting
    VOLUME /myvol

    USER

    设定容器运行时的用户与用户组,当没有指定USER指令时,默认采用管理员用户,语法如下:

    USER <user>[:<group>] or
    USER <UID>[:<GID>]

    WORKDIR

    指定当前工作的工作目录,docker官方推荐使用的指令,不建议使用"RUN cd"这样的方式来进行目录的切换,语法如下:

    WORKDIR /path/to/workdir

    示例如下:

    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN pwd

    ONBUILD

      当我们在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A镜像)不会产生实质性影响。但是当我们编写一个新的Dockerfile文件来基于A镜像构建一个镜像(比如为B镜像)时,这时构造A镜像的Dockerfile文件中的ONBUILD指令就生效了,在构建B镜像的过程中,首先会执行ONBUILD指令指定的指令,然后才会执行其它指令。需要注意的是,如果是再利用B镜像构造新的镜像时,那个ONBUILD指令就无效了,也就是说只能再构建子镜像中执行,对孙子镜像构建无效。其实想想是合理的,因为在构建子镜像中已经执行了,如果孙子镜像构建还要执行,相当于重复执行,这就有问题了。 语法如下:

    ONBUILD [INSTRUCTION]

    示例如下:

    # 第一个Dockerfile
    FROM ubuntu
    MAINTAINER hello
    ONBUILD RUN mkdir mydir
    
    # 第二个Dockerfile
    FROM imagea
    MAINTAINER hello1

    STOPSIGNAL

    设置容器优雅的退出进程与程序,这样可以保持数据的安全性与用户体验。语法如下:

    STOPSIGNAL signal

    示例:

    STOPSIGNAL sigkill

    信号参考大全:https://www.cnblogs.com/guge-94/p/11019605.html

    信号退出原理:https://www.jb51.net/article/96617.htm

    HEALTHCHECK

    对容器运行的指定内容做健康检查,语法如下:

    HEALTHCHECK [OPTIONS] CMD command
    HEALTHCHECK NONE

    选项讲解如下:

    --interval=DURATION (default: 30s)
    --timeout=DURATION (default: 30s)
    --start-period=DURATION (default: 0s)
    --retries=N (default: 3)
    1. interval:间隔(s秒、m分钟、h小时),从容器运行起来开始计时interval秒(或者分钟小时)进行第一次健康检查,随后每间隔interval秒进行一次健康检查;还有一种特例请看timeout解析。
    2. timeout:执行command需要时间,比如curl 一个地址,如果超过timeout秒则认为超时是错误的状态,此时每次健康检查的时间是timeout+interval秒
    3. retries:连续检查retries次,如果结果都是失败状态,则认为这个容器是unhealth的

    示例如下:

    HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1

    参考地址:https://blog.csdn.net/tech_salon/article/details/77255915

    SHELL

    用于指定执行程序所使用的解释器,一般主要应用与Windows场景,因为linux一般都是用bash,语法如下:

    SHELL ["executable", "parameters"]

    示例如下:

    FROM microsoft/windowsservercore
    
    # Executed as cmd /S /C echo default
    RUN echo default
    
    # Executed as cmd /S /C powershell -command Write-Host default
    RUN powershell -command Write-Host default
    
    # Executed as powershell -command Write-Host hello
    SHELL ["powershell", "-command"]
    RUN Write-Host hello
    
    # Executed as cmd /S /C echo hello
    SHELL ["cmd", "/S", "/C"]
    RUN echo hello
  • 相关阅读:
    错误 2 error C2059: 语法错误:“::”
    完全卸载session 所需要的函数
    header("Location:http://www.baidu.com");
    php str_pad() 用法
    php str_pad();
    设计模式系列-01-开篇
    博客园样式的设置系列-01-侧边栏和皮肤的设置
    vs20132015UML系列之-类图
    php获取当前时间和转换格式
    saltstack:multi-master configuration
  • 原文地址:https://www.cnblogs.com/guge-94/p/11076979.html
Copyright © 2011-2022 走看看