• Dockerfile详解与实践


    Dockerfile详解与实践
    Docker‘s Network
    Docker-Compose

    官方文档:https://docs.docker.com/engine/reference/builder/
    Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

    dockerfile每条指令都会构建一层镜像,一般分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动执行指令,#为 Dockerfile 中的注释符。

    01、Dockerfile总述

    docker build 基于dockerfile制作镜像。
    
    docker build [OPTIONS] PATH | URL | -
    OPTIONS参数
    -t, --tag list                Name and optionally a tag in the 'name:tag' format
    -c, --cpu-shares int          CPU shares (relative weight)
    -m, --memory bytes            Memory limit
    --build-arg list         	  Set build-time variables
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    02、指令:FROM

    FROM:指令必须是Dockerfile中非注释行的第一个指令,为镜像文件构建提供基础镜像环境。
    
    FROM <repository>[:<tag>]
    或:
    FROM <repository>@<digest>
    	<repository>:指定作为 base image 的名称
    	<tag>:base image 的标签,省略则默认为latest
    	<digest>:镜像的哈希值
    
    示例:
    FROM busybox:latest
    FROM redis:6.0.8
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    03、指令:MAINTAINER

    Dockerfile镜像维护者的详细信息,如姓名和邮箱地址。
    
    MAINTAINER <authtor's detail>
    
    示例:
    FROM busybox:latest
    MAINTAINER "Along "
    
    FROM busybox:latest
    MAINTAINER "Along "
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    04、指令:COPY

    用于从 docker 拷贝主机文件或目录 到 镜像中。
    COPY [--chown=<user>:<group>] <src>... <dest>
    COPY [--chown=<user>:<group>] ["",... ""]
    
    <src>:源路径,要复制的源文件或目录。
    <dest>:目标路径,即正在创建的镜像的文件系统路径(该路径不用事先建好)。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    05、指令:ADD

    指令类似于COPY指令,将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包。
    
    ADD [--chown=<user>:<group>] [--checksum=<checksum>] <src>... <dest>
    ADD [--chown=<user>:<group>] ["",... ""]
    
    1、拷贝单个文件
    ADD ./a.txt WORKDIR/b
    
    2、拷贝多个文件
    ADD指令支持通配符:
    # 拷贝当前目录下的michael文件夹的所有sh文件到/usr/bin目录下
    ADD ./michael/*.sh /usr/bin/
    
    # 拷贝当前目录下的michael文件夹的所有带后缀的文件到/usr/bin目录下
    ADD ./michael/*.* /usr/bin/
    
    # 拷贝当前目录下的michael文件夹的所有不带后缀的文件到/usr/bin目录下
    ADD ./michael/* /usr/bin/
    
    # 拷贝当前目录下的michael文件夹的所有文件到/usr/bin目录下(/usr/bin目录原有的文件会保留)
    ADD ./michael/ /usr/bin/
    
    3、拷贝文件夹
    ADD ./config /usr/bin/config
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    06、指令:ENV

    定义构建镜像的环境变量,可被Dockerfile文件中位于其后的其它指令(如ENV、ADD等)所调用。
    调用格式为 $variable_name${variable_name}。
    
    一次只能设置一个
    ENV key value
    一次可以设置多个键值对
    ENV key1=value1 key2=value2
    使用例子:
    ENV MY_PATH /usr/mytest
    WORKDIR $MY_PATHdocker run 命令中设置环境变量:
    docker run -e key1=value1 --env key2=value2 ubuntu
    docker run --env key1=value1 --env key2=value2 ubuntu
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    07、指令:VOLUME

    1、VOLUME-v指令一样,容器被删除以后映射在主机上的文件不会被删除。
    2、VOLUME指令只是起到了声明了容器中的目录作为匿名卷,并没有将匿名卷绑定到宿主机指定目录的功能。
    若Dockerfile中声明了VOLUME匿名卷,启动容器的时候,docker会在主机特定目录下面生成一个目录来绑定容器的匿名卷,如我测试的docker版本映射目录为:/var/lib/docker/volumes/{随机生成的唯一ID}/_data。(可以通过 docker inspect 容器ID 查看映射关系)。

    3、若-vVOLUME指定了不同的位置,会以-v设定的目录为准,其实VOLUME指令的设定的目的就是为了避免用户忘记指定-v的时候导致的数据丢失,那么如果用户指定了-v,自然而然就不需要VOLUME指定的位置了。

    容器数据卷,用于在image中创建一个默认挂载点目录,达到数据保存和持久化的目的。
    
    VOLUME <mountpoint>
    
    格式1:The value can be a JSON array, such as 
    VOLUME ["/var/log/"]
    VOLUME ["/var/log/", "/var/db"]
    
    格式2:a plain string with multiple arguments, such as 
    VOLUME /var/log
    VOLUME /var/log /var/db
    
    
    
    使用命令可查看到默认挂载点具体在主机上的挂载位置
    docker inspect fa158a
    [
        {
            "Id": "fa158a17f30e37e1edd9e9949d7974cdd22bbfba966ca95f14938c5aa5931140",
            "Created": "2022-11-06T16:38:58.485000851Z",
    		... 省略 ...............................
            "Mounts": [
                {
                    "Type": "volume",
                    "Name": "f657b5700e230bd6e4354dc6cc6861a4d28a8b091f97e00e03a102346b0bf6a7",
                    "Source": "/var/lib/docker/volumes/f657b5700e230bd6e4354dc6cc6861a4d28a8b091f97e00e03a102346b0bf6a7/_data",
    				"Destination": "/tmp",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                }
            ],
    		... 省略 ...............................
        }
    ]
    
    
    默认挂载点会将数据映射保存到/var/lib/docker/volumes/下的一个特定目录下
    /var/lib/docker/volumes/f657b5700e230bd6e4354dc6cc6861a4d28a8b091f97e00e03a102346b0bf6a7/_data
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    08、指令:RUN

    用于指定容器构建过程中运行的命令,其可以是任何命令,RUN是在 docker build时运行。
    RUN <command>
    或
    RUN ["", "", ""]
    
    第一种shell格式中,<command>通常是一个shell命令, 且以“/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,
    不能接收Unix信号,因此,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号;
    RUN yum -y install vim
    
    
    第二种exec格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的 <paramN>为传递给命令的选项或参数;
    然而,此种格式指定的命令不会以“/bin/sh -c”来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;
    不过, 如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。
    RUN ["/bin/bash", "-c", "", "", ""]
    RUN ["yum", "-y", "install", "vim"]
    RUN ["/bin/bash", "-c", "yum", "-y", "install", "vim"]
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    09、指令:CMD

    类似于RUN指令,CMD指令也可用于运行任何命令或应用程序
    RUN 运行于镜像文件构建过程中【镜像构建命令:RUN是在 docker build 时运行】。
    CMD 运行于基于Dockerfile构建出的新镜像启动一个容器时【容器启动命令:CMD是在 docker run 时运行】。
    
    CMD 的首要目的在于为启动的容器指定默认要运行的程序;
    CMD 会被 docker run 之后的参数替换;
    Dockerfile中可以存在多个CMD指令,但仅最后一个会生效;
    docker pull billygoo/tomcat8-jdk8
    
    可以看到猫:
    docker run -it -p 8080:8080 billygoo/tomcat8-jdk8
    docker run -it -p 8080:8080 30ef4019761d
    ### CMD ["catalina.sh", "run"]
    
    不可以看到猫:
    docker run -it -p 8080:8080 30ef4019761d /bin/bash
    ### CMD ["catalina.sh", "run"]
    ### CMD ["/bin/bash"]
    
    
    语法1:格式的意义同RUN;
    CMD <command>  
    语法2:格式的意义同RUN;
    CMD ["","",""] 
    语法3:用于为 ENTRYPOINT 指令提供默认参数;
    CMD ["",""]
    
    注:json数组中,要使用双引号,单引号会出错;
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    10、指令:ENTRYPOINT

    类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
    与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,
    这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
    不过,docker run命令的 --entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
    
    ENTRYPOINT command param1 param2
    或
    ENTRYPOINT ["executable", "param1", "param2"]
    
    docker run 命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
    Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
    
    
    
    命令格式:
    ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成 案例如下:
    
    -----Dockerfile-----start
    FROM nginx
    
    ENTRYPOINT ["nginx", "-c"] # 定参
    CMD ["/etc/nginx/nginx.conf"] # 变参
    # 假设已通过此 Dockerfile 构建了 nginx:test 镜像:
    -----Dockerfile-----end
    
    docker run nginx:test		# 实际执行命令 nginx -c /etc/nginx/nginx.conf
    docker run nginx:test -c /etc/nginx/new.conf  # 实际执行命令 nginx -c /etc/nginx/new.conf 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    11、指令:HEALTHCHECK

    HEALTHCHECK指令告诉Docker如何测试容器以检查它是否仍在工作。
    即使服务器进程仍在运行,这也可以检测出陷入无限循环且无法处理新连接的Web服务器等情况
    
    HEALTHCHECK [OPTIONS] CMD command (通过在容器内运行命令来检查容器运行状况)
    HEALTHCHECK NONE (禁用从基础映像继承的任何运行状况检查)
    
    OPTIONS 选项:
    --interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒
    -- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒
    --start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒
    --retries=N (default: 3):认为检测失败几次为宕机,默认3次
    
    返回值:
    0:容器成功是健康的,随时可以使用
    1:不健康的容器无法正常工作
    2:保留不使用此退出代码
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    12、指令:ONBUILD

    用于在Dockerfile中定义一个触发器
    Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,
    并以之构建新的映像文件
    在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件
    中的ONBUILD指令定义的触发器
    
    ONBUILD < Instruction>
    尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
    使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuil
    在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    13、指令:USER

    用于指定运行image时的或运行Dockerfile中任何RUN、CMD或EntRyPoInT指令指定的程序时的用户名或UID
    默认情况下,container的运行身份为root用户
    
    USER <user>[:<group>]
    或:
    USER <UID>[:<GID>]
    需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/ passwd中某用户的有效UID,否则,docker run命令将运行失败
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    14、指令:ARG

    ARG指令类似ENV,定义了一个变量;区别于ENV:用户可以在构建时docker build --build-arg <varname> = <value> 
    进行对变量的修改;ENV不可以
    如果用户指定了未在Dockerfile中定义的构建参数,那么构建输出警告
    
    ARG <name>[=<default value>]
    Dockerfile可以包含一个或多个ARG指令
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    15、指令:SHELL

    SHELL指令允许覆盖用于shell命令形式的默认shell。
    Linux上的默认shell是[“/ bin / sh”,“c”],在Windows上是[“cmd”,“/ S”,“/ C”]
    SHELL指令必须以JSON格式写入Dockerfile。
    SHELL ["executable", "parameters"]
    
    SHELL指令可以多次出现。
    每个SHELL指令都会覆盖所有先前的SHELL指令,并影响所有后续指令。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    16、指令:STOPSIGNAL

    STOPSIGNAL指令设置将发送到容器出口的系统调用信号
    此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如9,或者SIGNAME格式的信号名,例如SIGKILL。
    
    STOPSIGNAL signal
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    17、指令:EXPOSE

    用于为容器打开指定要监听的端口以实现与外部通信
    EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>]
    
    <protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
    EXPOSE指令可一次指定多个端口,例如:EXPOSE 11211/udp 11211/tcp
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    18、指令:WORKDIR

    用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
    WORKDIR <dirpath>
    
    
    使用例子:
    ENV MY_PATH /usr/mytest
    WORKDIR $MY_PATH
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    19、centos vim+ifconfig+jdk8 Dockerfile example

    docker run -it 5d0da3dc9764 /bin/bash
    
    
    
    1111111111、编写
    mkdir myDockerfile
    cd myDockerfile/
    
    vim Dockerfile
    -----Dockerfile-----start-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    FROM centos:7
    MAINTAINER michael_linux@163.com
    ENV MYWORKPATH /usr/local
    WORKDIR $MYWORKPATH
    #安装vim编辑器
    RUN yum -y install vim
    
    #安装ifconfig命令查看网络IP
    RUN yum -y install net-tools
    
    #安装java8及lib库
    RUN yum -y install glibc.i686
    RUN mkdir /usr/local/java
    #ADD 是相对路径jar,把jdk-8u191-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
    ADD jdk-8u191-linux-x64.tar.gz /usr/local/java/
    #配置java环境变量
    ENV JAVA_HOME /usr/local/java/jdk1.8.0_191
    ENV JRE_HOME $JAVA_HOME/jre
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
    ENV PATH $JAVA_HOME/bin:$PATH
    
    EXPOSE 80
    CMD echo $MYWORKPATH
    CMD echo "success--------------ok"
    CMD /bin/bash
    -----Dockerfile-----end-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    
    
    
    2222222222、构建
    格式: docker build -t 新镜像名字:TAG .
    docker build -t centosjava8:custom1.1 .
    # 命令最后的 点 不要忘记了哦
    
    
    3333333333、运行
    docker run -it centosjava8:custom1.1 /bin/bash
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    20、ubuntu net-tools+iproute2+inetutils-ping Dockerfile example

    1111111111、编写
    mkdir myUbuntuDockerfile
    cd myUbuntuDockerfile/
    
    vim Dockerfile
    -----Dockerfile-----start-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    FROM ubuntu
    MAINTAINER michael_linux@163.com
    ENV MYWORKPATH /usr/local
    WORKDIR $MYWORKPATH
    #更新
    RUN apt-get update
    #安装ifconfig
    RUN apt-get install -y net-tools
    #安装ip addr
    RUN apt-get install -y iproute2
    #安装ping
    RUN apt-get install -y inetutils-ping
    
    EXPOSE 80
    CMD echo $MYWORKPATH
    CMD echo "install success--------------ok"
    CMD /bin/bash
    -----Dockerfile-----end-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    
    
    
    2222222222、构建
    -t, --tag list       Name and optionally a tag in the 'name:tag' format
    格式: docker build -t 新镜像名字:TAG .
    docker build -t myubuntu:1.2 .
    # 命令最后的 点 不要忘记了哦
    
    
    3333333333、运行
    docker run -it myubuntu:1.2 /bin/bash
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    21、虚悬镜像

    仓库名、标签都是的镜像,俗称 dangling image

    1、 编写Dockerfile
    vim Dockerfile
    
    from ubuntu
    CMD echo 'action is success'
    
    2、构建镜像
    docker build .
    
    3、查看虚悬镜像
    docker image ls -f dangling=true
    
    4、删除虚悬镜像(dangling images无存在价值)
    docker image prune
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    22、由Dockerfile发布服务到docker

    1、springboot项目jar包
    链接: https://gitee.com/michael_linux/spring-security-study/tree/master/dockerfile-use

    2、编写 vim Dockerfile

    # 基础镜像使用java
    FROM java:8
    # 作者
    MAINTAINER michael_linux@163.com
    # VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
    VOLUME /tmp
    # 将jar包添加到容器中并更名为michael_docker.jar
    ADD dockerfile-use.jar michael_docker.jar
    # 运行jar包
    # RUN bash -c 'touch /michael_docker.jar'
    ENTRYPOINT ["java","-jar","/michael_docker.jar"]
    #暴露9001端口作为微服务
    EXPOSE 9001
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3、构建镜像

    docker build -t michael_docker:1.1 .
    
    • 1

    4、运行容器

    docker run -d -p 9001:9001 michael_docker:1.1
    
    • 1
  • 相关阅读:
    高级系统架构设计师_笔记_真题
    Scroll zkEvm技术设计全面思考
    新零售SaaS架构:促销系统架构设计
    Mysql 日志
    Nginx使用配置代理转发Windows远程桌面功能
    互联网大厂面试必问的40个SpringBoot面试题【建议收藏】
    anaconda 离线安装Python环境
    669. 修剪二叉搜索树 ●●
    华为云云耀云服务器L实例评测|云耀云服务器L实例部署ZFile在线网盘服务
    Linux学习之远程拷贝数据命令
  • 原文地址:https://blog.csdn.net/Michael_lcf/article/details/127697820