• Dockerfile详解


    Dockerfile介绍

    Dockerfile类似于shell的脚本,由一条条指令组成,Docker进程可以通过读取Dockerfile中的指令,依据指令内容自动构建生成镜像。

    dockerfile 官方文档

    Dockerfile常用指令

    FROM
    LABEL
    RUN
    EXPOSE
    COPY
    ADD
    ENV
    ARG
    USER
    CMD
    ENTRYPOINT
    VOLUME
    WORKDIR
    

    FROM: 指定基础镜像

    FROM指令:指定dockerfile的底层镜像,后续都每条指令都可以看做是在这个底层镜像上的叠加,Dockerfile一般都是以FROM指令开头,其镜像文件,一般选用官方提供的镜像较为安全,当然也可以是已经制作好的本地镜像。

    FROM [--platform=<platform>] <image> [AS <name>]
    FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
    FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
    
    --platform 指定镜像的平台,比如: linux/amd64, linux/arm64, or windows/amd64 tag 和 digest是可选项,如果不指定,默认为latest
    
    # 示例
    FROM scratch  #所有镜像的起源镜像
    FROM ubuntu
    FROM ubuntu:bionic
    FROM centos:7.9.2009
    

    LABEL: 指定镜像元数据

    LABEL指令:向镜像中添加元数据信息,例如 镜像的作者,镜像的信息,镜像的版本号,它是以键值对的方式来存储数据的,一个镜像可以有多个LABEL,可以写在一行中,也可以写在多行中,行尾使用 号分隔,推荐写在一行中,可以减少镜像的大小。

    LABEL <key>=<value> <key>=<value> <key>=<value> ...
    
    # 示例
    #一行格式
    LABEL label1="value1" label2="value2" label3="value3"
    
    #多行格式
    LABEL label1="value1" 
    	  label2="value2" 
    	  label3="value3"
    

    RUN: 执行 shell 命令

    RUN指令:在当前映像的顶部执行shell命令,并提交生成一层镜像,每一个RUN指令都会建立一个镜像层,所以尽可能将多个RUN合并成一条指令,以减少镜像层数,比如将多个shell命令通过 && 连接一起成为在一条指令。

    # RUN指令后面直接跟shell命令,默认为sh -c
    RUN <命令>
    
    # exec格式
    RUN ["executable", "param1", "param2"] (exec form)
    
    # exec格式只支持双引号,不支持单引号,也无法使用环境变量,但它可以指定其它shell。例如:
    RUN ["/bin/bash","-c","echo hello,world!"]
    
    # 示例
    RUN echo 'Welcome to Nginx in Docker !' > /usr/share/nginx/html/index.html
    RUN yum -y install epel-release 
        && yum -y install nginx 
        && rm -rf /usr/share/nginx/html/*
        && echo 'Welcome to Nginx in Docker !' > /usr/share/nginx/html/index.html
    

    注意事项:

    • 每条RUN命令的初始目录都是基于WOKRDIR目录,并不会因为上一条RUN命令进入了某个目录而影响后续的RUN命令的初始目录。

    EXPOSE:暴露端口

    EXPOSE指令:指定服务端容器打算监听的端口号,但实际上并不会主动发布端口,仅仅只是声明,只有在启动容器的时候通过-P或者-p参数,Docker才会真正将端口暴露出来使用。

    EXPOSE <port> [<port>/<protocol>...]
    
    # 示例
    EXPOSE 80 443
    EXPOSE 80/tcp
    EXPOSE 80/udp
    

    注意事项:

    • 默认情况下,EXPOSE使用TCP,当然也可以指定为UDP。
    • 即使Dockerfile文件中没有使用EXPOSE指令指定暴露端口,也可以在启动容器的时候通过-p参数来暴露指定的监听端口,所以,EXPOSE指令仅用于指定默认的暴露端口,通过-P参数才能进行真正的端口暴露。

    COPY:复制文件

    COPY指令:可以复制宿主机中的文件到容器中 ,并且连元数据等相关信息也一起复制,如读写执行权限,文件创建变更时间,但如果没有--chown指定属主,默认属主为容器root用户。

    # COPY指令有两种使用方式,如果路径中包含空格,需要使用第二种格式
    COPY [--chown=<user>:<group>] <src>... <dest>
    COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
    

    注意事项:

    • 可以指定多个,支持通配符,使用 Go’s filepath.Match rules。
    • 如果是目录,则将复制目录的整个内容,但目录本身不会被复制。
    • 基于当前Dockerfile的相对路径。
    • 是绝对路径或相对于WORKDIR的路径。
    • 如果不是以斜杠/结束,它将被认为是源文件拷贝后的重命名文件,如果以结尾斜杠/结束,它将被视为目录,即将源文件拷贝到目录下。
    • 当指定了多个,或者使用了通配符的情况下,必须以/结尾
    • --chown只支持linux系统。
    • 如果 < dest > 不存在,则递归创建所有不存在的目录。

    ADD:复制和解压文件

    ADD指令:该指令不仅支持复制文件,如果复制的文件是一个压缩文件,还支持自动解压缩。另外还支持URL下载,下载后的文件权限默认为600。

    # 和COPY指令类似,有两种使用方式,如果路径中包含空格,需要使用第二种格式
    ADD [--chown=<user>:<group>] <src>... <dest>
    ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
    

    注意事项:

    • 参考COPY指令的注意事项 ,ADD指令基本都适用。
    • 如果URL是一个tar.gz类的压缩文件,下载后并不会自动解压。

    ENV: 设置环境变量

    ENV指令:用来定义环境变量。可以被所有后续指令(如:ENV,ADD,COPY,RUN等)进行引用,
    并在容器运行时保持此值。

    # 只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成部分
    ENV <key> <value>
    
    # 支持多个key赋值,定义多个变量建议使用,减少镜像层
    ENV <key1>=<value1> <key2>=<value2>  
        <key3>=<value3> ...
    
    #如果<value>中包含空格,可以以反斜线进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行
    
    # 如果只在构筑镜像的时候使用一次变量,可以考虑在RUN命令中直接设置
    RUN <key>=<value> <command>
    
    #引用变量
    RUN $key .....
    
    #变量支持高级赋值格式
    ${key:-word}
    ${kye:+word}
    

    ARG: 构建参数

    ARG指令:在镜像构建阶段指定变量,和ENV不同的是,容器运行后并不会保留变量。也可以在构建镜像时使用docker build命令的--build-arg = 将变量传递进Dockerfile覆盖原有的AGR变量值。

    ARG <name>[=<default value>]
    
    # 示例
    FROM centos:7.9.2009   
    RUN touch ${test:-aaa}.txt
    ARG test=demo
    RUN touch ${test:-bbb}.txt
    
    # 上面示例最终会生成一个aaa.txt文件和demo.txt文件
    [root@ubuntu2004:/docker/test]# docker run -it --name t4 fbf6635fb360 bash
    [root@0c5878a01837 /]# ls
    aaa.txt            bin       dev  home  lib64  mnt  proc  run   srv  tmp  var
    anaconda-post.log  demo.txt  etc  lib   media  opt  root  sbin  sys  usr
    

    注意事项:

    • 如果同时存在同名的ENV和ARG变量,ENV变量将覆盖ARG变量。
    • ARG变量定义从Dockerfile中定义的行往后才开始生效。
    • 不建议在构建镜像时使用-build-arg参数来传递如密钥,用户凭据等信息,因为使用docker history命令可以看得到。

    USER:指定用户

    USER指令:用于指定运行容器时的用户名或者UID。

    USER <user>[:<group>]
    USER <UID>[:<GID>]
    
    # 示例
    RUN groupadd -r test 
    	&& useradd -r -g test test
    USER test
    

    注意事项:

    • 用户必须提前创建好,否则会报错。
    • 如果没有指定用户,默认使用root身份运行容器。
    • Dockerfile后续的指令例如RUN,CMD,ENTRYPOINT也会使用该指定用户。

    CMD:容器运行命令

    CMD指令:用来指定在启动容器时默认执行的命令,该命令运行结束后,容器将停止运行,所以一般情况下CMD均为可持续运行的前台命令。使用docker run运行容器的时候可以后续指定具体命令来覆盖CMD中的命令。

    # exec格式,不支持环境变量,第一个参数必须为绝对路径
    CMD ["executable","param1","param2"]
    
    # 用于给ENTRYPOINT传递参数
    CMD ["param1","param2"]
    
    # 之间跟shell命令和参数,支持环境变量,默认使用/bin/sh
    CMD command param1 param2
    
    # 示例
    CMD ["nginx","-g","demon off;"]
    

    注意事项:

    • Dockerfile中只能有一个CMD命令,如果有多个,只有最后一条会生效。
    • 当Dockerfile中同时还有ENTRYPOINT指令时,CMD只能当做其参数使用。

    ENTRYPOINT:入口点

    ENTRYPOINT指令:该指令功能类似于CMD指令,所不同的是ENTRYPOINT指令中的命令不能被docker run后续的命令所覆盖,而是将其追加作为参数使用。

    如果想要覆盖Dockerfile中的ENTRYPOINT指令,可以在docker run后使用--entrypoint参数来指令新的命令作为入口点。

    ENTRYPOINT指令可以结合exec命令,在启动容器的时候运行脚本。

    # exec格式
    ENTRYPOINT ["executable", "param1", "param2"]
    
    # shell格式
    ENTRYPOINT command param1 param2
    

    VOLUME:匿名卷

    VOLUME指令:用于为容器中的某个目录创建一个挂载点来存放需要保存的数据,即使容器被删除后,该目录对应的宿主机目录也会一直存在,宿主机目录的默认路径为 /var/lib/docker/volumes/<volume_id>/_data ,因为是匿名卷,不太好查找,可以使用docker inspect <image_id>l来查看具体的目录信息。

    我们在使用docker run命令启动容器的时候可以使用 -v 参数来指定具体的目录挂载关系,因此该指令也不算太常用,当然,用户在使用docker run命令启动容器的时候可能会忘记使用 -v 参数指定挂载点,因此对于有重要数据的容器来说,VOLUME指令相当于多了一层保障。

    VOLUME ["/data"]
    VOLUME ["/data1","/data2"]
    

    WORKDIR:工作目录

    WORKDIR指令:该指令可以为后续的RUN,CMD,ENTRYPOINT,COPY和ADD指令配置默认的工作目录,当容器运行后,也会进入WORKDIR所指定的目录。

    WORKDIR /path/to/workdir
    

    使用docker build命令构建镜像

    查看帮助:

    [root@ubuntu2004:~]# docker build --help
    
    Usage:	docker build [OPTIONS] PATH | URL | -
    
    Build an image from a Dockerfile
    
    Options:
          --add-host list           Add a custom host-to-IP mapping (host:ip)
          --build-arg list          Set build-time variables
          --cache-from strings      Images to consider as cache sources
          --cgroup-parent string    Optional parent cgroup for the container
          --compress                Compress the build context using gzip
          --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period
          --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota
      -c, --cpu-shares int          CPU shares (relative weight)
          --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)
          --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)
          --disable-content-trust   Skip image verification (default true)
      -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
          --force-rm                Always remove intermediate containers
          --iidfile string          Write the image ID to the file
          --isolation string        Container isolation technology
          --label list              Set metadata for an image
      -m, --memory bytes            Memory limit
          --memory-swap bytes       Swap limit equal to memory plus swap: '-1' to
                                    enable unlimited swap
          --network string          Set the networking mode for the RUN instructions
                                    during build (default "default")
          --no-cache                Do not use cache when building the image
      -o, --output stringArray      Output destination (format: type=local,dest=path)
          --platform string         Set platform if server is multi-platform capable
          --progress string         Set type of progress output (auto, plain, tty).
                                    Use plain to show container output (default "auto")
          --pull                    Always attempt to pull a newer version of the image
      -q, --quiet                   Suppress the build output and print image ID on success
          --rm                      Remove intermediate containers after a successful
                                    build (default true)
          --secret stringArray      Secret file to expose to the build (only if
                                    BuildKit enabled): id=mysecret,src=/local/secret
          --security-opt strings    Security options
          --shm-size bytes          Size of /dev/shm
          --squash                  Squash newly built layers into a single new layer
          --ssh stringArray         SSH agent socket or keys to expose to the build
                                    (only if BuildKit enabled) (format:
                                    default|<id>[=<socket>|<key>[,<key>]])
          --stream                  Stream attaches to server to negotiate build context
      -t, --tag list                Name and optionally a tag in the 'name:tag' format
          --target string           Set the target build stage to build.
          --ulimit ulimit           Ulimit options (default [])
    

    示例:

    [root@ubuntu2004:~]# docker build -t cenos7.9:base-v1.0 .
    

    范例:Tomcat业务镜像制作

    1. 制作 CentOS 基础镜像

    [root@ubuntu2004:/docker/centos]# ls
    CentOS7.repo  Dockerfile
    
    
    [root@ubuntu2004:/docker/centos]# cat CentOS7.repo
    [Base-Package]
    name=Base
    baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/7/os/x86_64/
            http://mirrors.aliyun.com/centos/7/os/x86_64/
            http://mirrors.huaweicloud.com/centos/7/os/x86_64/
    gpgcheck=1
    gpgkey=http://mirrors.tuna.tsinghua.edu.cn/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7
    
    [Epel]
    name=epel
    baseurl=http://mirrors.tuna.tsinghua.edu.cn/epel/7/x86_64/
            http://mirrors.aliyun.com/epel/7/x86_64/
            http://mirrors.huaweicloud.com/epel/7/x86_64/
    gpgcheck=1
    gpgkey=http://mirrors.tuna.tsinghua.edu.cn/epel/RPM-GPG-KEY-EPEL-7
    
    [Extras]
    name=extras
    baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64/
            http://mirrors.aliyun.com/centos/7/extras/x86_64/
            http://mirrors.huaweicloud.com/centos/7/extras/x86_64/
    gpgcheck=1
    gpgkey=http://mirrors.tuna.tsinghua.edu.cn/centos/RPM-GPG-KEY-CentOS-Official
    
    
    [root@ubuntu2004:/docker/centos]# cat Dockerfile 
    FROM centos:7.9.2009  
    LABEL maintainer=wuvikr message=centos7.9_base_image
    COPY CentOS7.repo /etc/yum.repos.d/
    RUN find /etc/yum.repos.d ! -name CentOS7.repo -a -type f -exec rm -rf {} ; 
        && yum -y install vim curl wget telnet tree wget bash-completion net-tools iproute lrzsz lsof zip unzip nfs-utils gcc make glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel zlib-devel rsync tcpdump psmisc bzip2 
        && yum clean all 
        && rm -f /etc/localtime 
        && ln -s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    RUN groupadd www -g 2020 && useradd www -u 2020 -g www
        
    
    [root@ubuntu2004:/docker/centos]# docker build -t centos7.9:base .
    

    2. 制作构建 JDK 镜像

    [root@ubuntu2004:/docker/jdk]# ls
    Dockerfile  jdk-8u271-linux-x64.tar.gz  jdk.sh
    
    
    [root@ubuntu2004:/docker/jdk]# cat jdk.sh 
    export JAVA_HOME=/usr/local/jdk
    export PATH=$JAVA_HOME/bin:$PATH
    export JRE_HOME=$JAVA_HOME/jre
    export CLASSPATH=$JAVA_HOME/lib/:$JRE_HOME/lib/
    
    
    [root@ubuntu2004:/docker/jdk]# cat Dockerfile 
    FROM centos7.9:base
    LABEL maintainer=wuvikr message=JDK8u271-CentOS7.9
    ADD jdk-8u271-linux-x64.tar.gz /usr/local/src/
    RUN ln -s /usr/local/src/jdk1.8.0_271 /usr/local/jdk
    COPY jdk.sh /etc/profile.d/
    ENV JAVA_HOME="/usr/local/jdk" PATH="${JAVA_HOME}/bin:${PATH}" 
        JRE_HOME="${JAVA_HOME}/jre" CLASSPATH="${JAVA_HOME}/lib/:${JRE_HOME}/lib/"
    
    
    [root@ubuntu2004:/docker/jdk]# docker build -t centos7.9-jdk:8u271 .
    

    3. 制作Tomcat镜像

    [root@ubuntu2004:/docker/tomcat]# ls
    apache-tomcat-8.5.61.tar.gz  Dockerfile
    
    
    [root@ubuntu2004:/docker/tomcat]# cat Dockerfile 
    FROM centos7.9-jdk:8u271
    LABEL maintainer=wuvikr message=Tomcat8.5.61-JDK8u271-Centos7.9
    RUN mkdir /apps
    ADD apache-tomcat-8.5.61.tar.gz /apps/
    RUN ln -s /apps/apache-tomcat-8.5.61 /apps/tomcat
    ENV TZ="Asia/Shanghai" LANG="en_US.UTF-8" TERM="xterm" TOMCAT_MAJOR_VERSION="8" 
        TOMCAT_MINOR_VERSION="8.5.61" CATALINA_HOME="/apps/tomcat" 
        APP_DIR="${CATALINA_HOME}/webapps" PATH="/apps/tomcat/bin:${PATH}"
    
    
    [root@ubuntu2004:/docker/tomcat]# docker build -t centos7.9-tomcat:8.5.61 .
    

    4. 制作web业务镜像

    [root@ubuntu2004:/docker/web1]# ls
    app.tar.gz  Dockerfile  run.sh  server.xml
    
    
    [root@ubuntu2004:/docker/web1]# cat run.sh
    #!/bin/bash
    su - www -c "/apps/tomcat/bin/catalina.sh run"
    
    
    [root@ubuntu2004:/docker/web1]# cat Dockerfile 
    FROM centos7.9-tomcat:8.5.61
    LABEL maintainer=wuvikr message=WEB1-Tomcat8.5.61-JDK8u271-Centos7.9
    COPY server.xml /apps/tomcat/conf/server.xml
    ADD app.tar.gz /data/tomcat/webapps/ROOT/
    COPY run.sh /apps/tomcat/bin/
    RUN echo "nameserver 114.114.114.114" >> /etc/resolv.conf 
        && chown -R www.www /apps/ /data/
    EXPOSE 8080 8009
    CMD ["/apps/tomcat/bin/run.sh"]
    
    
    [root@ubuntu2004:/docker/web1]# docker build -t centos7.9-tomcat8.5.61-web1:app .
    
  • 相关阅读:
    userAgent判断当前设备类型
    h5+css3最简单的图片飞入以及淡入淡出效果
    ruby的form中常用的控件
    初识swipe.js
    后缀为7z的文件解码
    python all()函数
    flask web表单
    flask过滤器
    flask学习笔记1.21
    py学习笔记1.13、1.14
  • 原文地址:https://www.cnblogs.com/wuvikr/p/14319215.html
Copyright © 2020-2023  润新知