(四) Docker之Dockerfile编写与指令解析,自定义镜像实战

1. Dockerfile介绍

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。类似于Makefile。

构建三个步骤:

  1. 编写Dockerfile文件
  2. docker build
  3. docker run

1.1 docker build

docker build 命令可以设置编译镜像时,使用的CPU数量、内存大小、Dockerfile文件路径、编译参数等。docker build 命令的用法如下。
在这里插入图片描述编译镜像由Docker Daemon完成。这是最简单的编译过程。
# docker build -t <image_name>

docker build的命令格式。
Usage: docker build [OPTIONS] PATH | URL | -

PATH是编译镜像使用的工作目录,Docker Daemon在编译开始时,扫描PATH中的所有文件。可以在编译目录中加入.dockerignore,过滤不需要的文件。Docker Daemon在编译时,会忽略.dockerignore中的文件。

默认情况下,Docker Daemon会从PATH 或 GIT中读取Dockerfile。如果需要使用其他的Dockerfile,可以使用 -f 参数。
# docker build -f ./Dockerfile .
使用 -t 给镜像打标签
# docker build -t mycentos/centos .

1.2 dockerignore文件

在编译开始之前,Docker Daemon会读取编译目录中的.dockerignore文件,忽略其中的文件和目录。可以在.dockerignore文件中加入文件和目录规则,忽略多个文件。

*/temp*
*/*/temp*
temp?

*.md
!README.md
*/temp* 忽略一级子目录下,以temp开头的所有文件和目录。
*/*/temp* 忽略二级子目录下,以temp开头的所有文件和目录。
temp? 忽略当前目录下,以temp开头,名字长度为5个字符的文件和目录。
Docker Daemon会读取 ! 后面的文件。上例中会读取README.md文件,并忽略所有的md文件。

1.3 Dockerfile格式

Dockerfile 中的每条指令由 指令+参数 组成,中间以空格隔离。# 后面为注释内容,# 可以写在任何位置。

指令不区分大小写,为了便于区分,一般指令使用大写,参数使用小写。Dockerfile中的第一条指令必须是FROM,设置基础镜像。

2. Dockerfile构建过程解析

2.1 Dockerfile内容基础知识:

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. #表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交

2.2 Docker执行Dockerfile的大致流程:

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态。

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
在这里插入图片描述

2.3 Dockerfile、镜像和容器三者关系

  1. Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
  2. Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
  3. Docker容器,容器是直接提供服务的。

3. DockerFile体系结构(指令详解)

Dockerfile 是Docker在编译镜像时执行的脚本文件,由很多条指令组成,这些指令按顺序排列。每条指令在编译镜像的过程中,执行相应的程序,完成某项功能。下面将介绍每条指令的功能。

  1. FROM指令
    基础镜像,当前新镜像是基于哪个镜像的。
    在基础镜像中,加入提供服务的程序和程序所需要的依赖包,定制自己的镜像。
    FROM指令格式

    FROM <image>
    FROM <image>:<tag>
    FROM <image>@<digest>
    

    可以在一个Dockerfile文件中加入多条FROM指令,一次生成多个镜像。两条FROM指令之间的内容放在一个镜像中。
    tag和digest是可选项。如果忽略tag,会使用latest镜像。

  2. MAINTAINER指令
    设置镜像作者。
    MAINTAINER指令格式

    MAINTAINER <name>
    
  3. RUN指令
    容器构建时需要运行的命令。

    RUN指令会生成一个新的容器,在容器中执行脚本,这个容器使用当前的镜像。脚本正常执行完后,Docker Daemon 会把容器提交作为一个中间镜像,供后面指令使用。
    RUN指令的格式

    RUN <command>
    RUN ["executable","param1","param2"]
    

    RUN指令执行由两种方式,第一种为shell方式,使用 /bin/sh -c <command>运行脚本。可以在这种方式中使用 \ ,把脚本分成多行。

    RUN source $HOME/.bashrc ;\
    echo $HOME
    

    第二种方式为exec方式。镜像中没有/bin/sh,或者要使用其他shell,私用这种方式。

    RUN ["/bin/bash","-c","echo hello"]
    
  4. EXPOSE指令
    当前容器对外暴露出的端口,记录容器启动时监听哪些端口。

    EXPOSE <port> [<port>...]
    
  5. WORKDIR指令
    指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点.
    设置RUN、CMD、ENTRYPOINT、ADD、COPY、指令的工作目录。

    WORKDIR指令的格式

    WORKDIR /path/to/workdir
    
  6. ENV指令
    用来在构建镜像过程中设置环境变量。

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

    这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
    也可以在其它指令中直接使用这些环境变量.

  7. ADD指令
    使用ADD指令把文件复制到镜像中。
    将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包。

    ADD指令格式

    ADD <src> ... <dest>
    ADD ["<src>",..."<dest>"]
    

    当路径中有空格时,需要使用第二种格式。

  8. COPY指令
    类似ADD,拷贝文件和目录到镜像中。
    将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。

    COPY指令格式

    COPY <src>...<dest>
    COPY ["<src>",..."<dest>"]
    
  9. VOLUME指令
    容器数据卷,用于数据保存和持久化工作。
    使用VOLUME指令设置容器的挂载点。

    VOLUME指令格式

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

    Docker Daemon会把主机目录或者数据卷容器挂在到这些挂载点。第一种格式为JSON格式,必须使用双引号。第二种格式把多个目录通过空格连接起来。

  10. CMD指令
    指定一个容器启动时要运行的命令

    使用CMD指令设置容器的启动命令,Dockerfile只能有一条CMD指令,如果写了多条CMD指令,只有最后一条CMD指令有效。

    CMD指令格式

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

    第一种是exec方式,第二种是ENTRYPOINT参数方式,第三种是shell方式。

  11. ENTRYPOINT指令
    指定一个容器启动时要运行的命令。

    使用ENTRYPOINT指令设置容器的入口程序。

    ENTRYPOINT指令格式

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

    入口程序有两种格式:第一种为exec方式,第二种为shell方式。第二种方式使用/bin/sh -c 运行入口程序,此时入口程序不能接收信号量。运行docker stop <container>时,程序不能接收SIGTERM。

    入口程序是容器启动时执行的程序,docker run 命令中最后的命令将作为参数传递给入口程序。

    如果Dockerfile有多条ENTRYPOINT,只有最后的ENTRYPOINT指令生效。

  12. ONBUILD指令
    当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发。

    使用ONBUILD指令设置子镜像的编译钩子指令。

    ONBUILD指令格式

    ONBUILD [INSTRUCTION]
    

    当从该镜像生成子镜像时,会调用ONBUILD指令。子镜像在编译过程中,首先会执行父镜像中的ONBUILD指令。所有的编译指令都可以称为钩子指令。

  13. USER指令
    USER指令设置用户名或UID

    USER daemon
    
  14. ARG指令
    使用ARG实例设置编译变量。
    ARG指令格式

    	ARG <name> [=<default value>]
    

    编译镜像时,可以通过 docker build --build-arg <var>=<value>设置这些变量。如果docker build设置的编译变量没有通过ARG定义,则Docker Daemon会报错。

    定义编译变量

    FROM busybox
    ARG user
    

    可以为编译变量设置默认值

    FROM busybox
    ARG user=zxg
    

    ARG从定义它的地方开始生效,而不是调用的地方

    FROM busybox
    ARG user
    USER $user
    

    编译时,设置编译变量的值
    # docker build --build-arg user=zxg Dockerfile

CMD、ENTRYPOINT和RUN的区别

  • RUN指令是设置编译镜像时执行的脚本和程序,镜像编译完成,RUN指令的生命周期结束。

容器启动时,可以通过CMD和ENTRYPOINT设置启动程序,两者有很大的区别和紧密的联系。

  • CMD叫做容器默认启动命令,既然是默认,就可以被替换掉。若在Docker run命令末尾添加Command,则替换镜像中CMD设置的启动程序。

  • ENTRYPOINT叫做入口程序,不能被docker run 命令末尾的Command替换。docker run 命令末尾的Command会被当作字符串,传递给ENTRYPOINT,作为参数。在docker run中,可以加入--entrypoint 替换镜像中的入口程序.

    遵循规则:

    1. 在Dockerfile中,至少应该有一条CMD或ENTRYPOINT指令。
    2. 当使用容器作为一个程序容器时,应使用ENTRYPOINT定义程序入口。
    3. 在Dockerfile中,如果同时定义了ENTRYPOINT和CMD,CMD会作为参数传递给ENTRYPOINT。
    4. 在docker run 末尾加入Command,会覆盖镜像中的CMD。
    5. 在docker run 中加入 --entrypoint,会覆盖镜像中的ENTRYPOINT。

4. 自定义镜像(mycentos)

  1. 运行一个centos容器。
    在这里插入图片描述默认登录在根目录/
    在这里插入图片描述发现不支持vim和ifconfig命令。

  2. 自定义mycentos目的使我们自己的镜像具备如下功能:

    • 登录的默认路径为 /root
    • 支持vim编辑器
    • 查看网络配置ifconfig支持
  3. 编写Dockerfile文件

    FROM centos
    
    MAINTAINER zxg
    
    ENV MYPATH /root
    WORKDIR $MYPATH
    
    RUN yum -y install vim
    RUN yum -y install net-tools
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "------successk----"
    CMD /bin/bash
    

    ENV用来在构建镜像过程中设置环境变量。
    WORKDIR用来设置工作目录。
    RUN 命令安装vim和net-tools。

  4. 使用docker build命令生成镜像
    [root@zxg mydocker]# docker build -f ./Dockerfile -t mycentos:1.0 .在这里插入图片描述mycentos镜像已经生成。
    在这里插入图片描述

  5. 运行
    [root@zxg ~]# docker run -it --name mycentos01 mycentos:1.0
    在这里插入图片描述发现此时工作目录为 /root,
    并且支持vim和ifconfig命令。

  6. 列出镜像的变更历史
    在这里插入图片描述

相关博客

(一) Docker介绍与安装、测试和常用命令等。一篇文章足以。

(二) Docker 镜像与容器的区别与存储结构

(三) Docker容器数据卷 详细讲解

猜你喜欢

转载自blog.csdn.net/Zhangxg0206/article/details/110450283