Docker专题(七)-DockerFile详解

1.DockerFile是什么

当我们从docker镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。

1.从已经创建的容器中更新镜像,并且提交这个镜像
2.使用 Dockerfile 指令来创建一个新的镜像

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。DockerFile是描述镜像的一种文件!

DockerFile是镜像的说明书,里面有一系列的执行,告诉Docker如何构建镜像!

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

  • Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

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

  • Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;

  • Docker容器,容器是直接提供服务的。

  • 构建三步骤

编写Dockerfile文件 -----> 编写DockerFile文件
docker build      -----> 构建镜像
docker run        -----> 使用镜像启动容器

DockerFile就是镜像的描述文件!

2.DockerFile文件什么样

2.1.以我们熟悉的CentOS为例

网站:https://hub.docker.com/_/centos/
在这里插入图片描述
在这里插入图片描述

2.2.一个Dockerfile的示例如下所示

#基于centos镜像
FROM centos

#维护人的信息
MAINTAINER The CentOS Project <[email protected]>

#安装httpd软件包
RUN yum -y update
RUN yum -y install httpd

#开启80端口
EXPOSE 80

#复制网站首页文件至镜像中web站点下
ADD index.html /var/www/html/index.html

#复制该脚本至镜像中,并修改其权限
ADD run.sh /run.sh
RUN chmod 775 /run.sh

#当启动容器时执行的脚本文件
CMD ["/run.sh"]
由上可知,Dockerfile结构大致分为四个部分:
  (1)基础镜像信息
  (2)维护者信息
  (3)镜像操作指令
  (4)容器启动时执行指令。
Dockerfile每行支持一条指令,每条指令可带多个参数,支持使用以#号开头的注释。下面会对上面使用到的一些常用指令做一些介绍。

2.3.DockerFile构建过程解析

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

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

  • 小结
    从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:
    1:Dockerfile是软件的原材料
    2:Docker镜像是软件的交付品
    3**:Docker容器**则可以认为是软件的运行态。

3.Dockerfile常用指令

在这里插入图片描述

3.1.FROM

指明构建的新镜像是来自于哪个基础镜像,例如:

FROM centos:6

基础镜像不存在会在Docker Hub上拉去(一般会是文件的第一个指令) 使用格式:
FROM <镜像>:[tag]

3.2.MAINTAINER

指明镜像维护着及其联系方式(一般是邮箱地址),例如

MAINTAINER BRUCELIU<[email protected]>

不过,MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者,例如:

LABEL maintainer="bruceliu.cn"

[逐渐废弃] LABLE --替代MAINTANIER 具体使用: LABLE maintainer=“作者信息”

3.3.RUN

RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。其格式有两种:
• shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 RUN 指令就是这种格式.
• exec 格式:RUN [“可执行文件”, “参数1”, “参数2”],这更像是函数调用中的格式。
使用格式:

RUN RUN ["","",""]

构建镜像时运行的Shell命令,例如:

RUN ["yum", "install", "httpd"]

RUN yum install httpd

RUN 就像 Shell 脚本一样可以执行命令,那么我们是否就可以像 Shell 脚本一样把每个命令对应一个 RUN 呢?比如
这样:

RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget http://download.redis.io/releases/redis-4.0.1.tar.gz
RUN tar xzf redis-4.0.1.tar.gz
RUN cd redis-4.0.1

Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。 而上面的这种写法,创建了 多 层镜像。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。 这是很多初学 Docker 的人常犯的一个错误。

Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。上面的Dockerfile 正确的写法应该是这样

FROM centos

RUN apt-get update \
&& apt-get install -y gcc libc6-dev make \
&& wget http://download.redis.io/releases/redis-4.0.1.tar.gz \
&& tar xzf redis-4.0.1.tar.gz \
&& cd redis-4.0.1

首先,之前所有的命令只有一个目的,就是编译、安装 redis 可执行文件。因此没有必要建立很多层,这只是一层的事情。因此,这里没有使用很多个 RUN 对一一对应不同的命令,而是仅仅使用一个 RUN 指令,并使用 && 将各个所需命令串联起来。将之前的 7 层,简化为了 1 层。

在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写Shell 脚本,而是在定义每一层该如何构建且,这里为了格式化还进行了换行。Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障更为容易,这是一个比较好的习惯。

3.4.CMD

启动容器时执行的Shell命令,例如:

CMD ["-C", "/start.sh"] 
CMD ["/usr/sbin/sshd", "-D"] 
CMD /usr/sbin/sshd -D

3.5.EXPOSE

声明容器运行的服务端口,为容器打开指定要监听的端口以实现与外部通信,例如:

EXPOSE 80 443

3.6.ENV

ENV指令可以用于为docker容器设置环境变量 ENV设置的环境变量,可以使用 docker inspect命令来查看。同时还可以使用docker run --env =来修改环境变量。

具体用法:
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin/

3.7.ADD

类似COPY命令,拷贝文件或目录到镜像中,例如:

ADD <src>...<dest>

ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html

3.8.COPY

拷贝文件或目录到镜像中,用法同ADD,只是不支持自动下载和解压,例如:

COPY ./start.sh /start.sh

3.9.ENTRYPOINT

启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序,例如:

ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
ENTRYPOINT /bin/bash -C '/start.sh'

PS:Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。

3.10. VOLUME

创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。例如:

VOLUME ["/var/lib/mysql"]

只能定义docker管理的卷: VOLUME /data/mysql运行的时候会随机在宿主机的目录下生成一个卷目录!
一般不会在Dockerfile中用到,更常见的还是在docker run的时候指定-v数据卷。

3.11 USER

为RUN、CMD和ENTRYPOINT执行Shell命令指定运行用户,例如:

USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER bruceliu

3.12 WORKDIR

Docker 默认的工作目录是/,只有 RUN 能执行 cd 命令切换目录,而且还只作用在当下下的 RUN,也就是说每一个 RUN 都是独立进行的。

如果想让其他指令在指定的目录下执行,就得靠 WORKDIR。WORKDIR 动作的目录改变是持久的,不用每个指令前都使用一次 WORKDIR。

WORKDIR /usr/local/tomcat/

3.13.小总结

在这里插入图片描述

4.DockerFile案例

4.1.Base镜像(scratch)

Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的
在这里插入图片描述

4.2.自定义镜像mycentos

Docker Hub默认CentOS镜像什么情况??
在这里插入图片描述

  • 准备编写DockerFile文件
[root@localhost myfile]# pwd
/root/myfile
[root@localhost myfile]# vi mycentos_dockerfile
  • myCentOS内容DockerFile
FROM centos
MAINTAINER bruceliu<bruceliu167@126.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
  • 构建
    命令:

docker build -t 新镜像名字:TAG .
会看到 docker build 命令最后有一个 .
. 表示当前目录

[root@localhost myfile]# docker build -f /root/myfile/mycentos_dockerfile -t mycentos:1.3 .
Sending build context to Docker daemon 2.048 kB
Step 1/10 : FROM centos
 ---> 9f38484d220f
Step 2/10 : MAINTAINER bruceliu<bruceliu167@126.com>
 ---> Using cache
 ---> 281446cb753d
Step 3/10 : ENV MYPATH /usr/local
 ---> Using cache
 ---> 2e09cdb61576
Step 4/10 : WORKDIR $MYPATH
 ---> Using cache
 ---> 4aa136d65f26
Step 5/10 : RUN yum -y install vim
 ---> Using cache
 ---> 585392f09407
Step 6/10 : RUN yum -y install net-tools
 ---> Using cache
 ---> 9c7971b08e59
Step 7/10 : EXPOSE 80
 ---> Using cache
 ---> 6741c0b61390
Step 8/10 : CMD echo $MYPATH
 ---> Using cache
 ---> fb1b4b72ba02
Step 9/10 : CMD echo "success--------------ok"
 ---> Using cache
 ---> 3d636347cc9a
Step 10/10 : CMD /bin/bash
 ---> Using cache
 ---> 720d4eb5c5f0
Successfully built 720d4eb5c5f0
  • 运行
    docker run -it 新镜像名字:TAG
    可以看到,我们自己的新镜像已经支持vim/ifconfig命令,扩展成功了。
[root@localhost ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED                  SIZE
docker.io/mongo       latest              9c02a5a12c52        Less than a second ago   413 MB
mycentos              1.3                 720d4eb5c5f0        50 minutes ago           480 MB
bruceliu/centos9527   latest              071e944a589b        8 hours ago              202 MB
bruceliu/tomcat       7-jre7              a66f9aba334d        13 hours ago             359 MB
docker.io/tomcat      7-jre7              47c156f4d4e3        5 weeks ago              359 MB
docker.io/mysql       latest              7bb2586065cd        2 months ago             477 MB
docker.io/centos      7                   9f38484d220f        3 months ago             202 MB
docker.io/centos      latest              9f38484d220f        3 months ago             202 MB
[root@localhost ~]# docker run -it mycentos:1.3
[root@50784a17d114 local]# pwd
/usr/local
[root@50784a17d114 local]# vi 1.txt
[root@50784a17d114 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.3  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:3  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:11:00:03  txqueuelen 0  (Ethernet)
        RX packets 8  bytes 656 (656.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 656 (656.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 列出镜像的变更历史
    命令:

docker history 镜像名

[root@localhost ~]# docker history 720d4eb5c5f0
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
720d4eb5c5f0        53 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/b...   0 B                 
3d636347cc9a        53 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "ec...   0 B                 
fb1b4b72ba02        53 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "ec...   0 B                 
6741c0b61390        53 minutes ago      /bin/sh -c #(nop)  EXPOSE 80/tcp                0 B                 
9c7971b08e59        53 minutes ago      /bin/sh -c yum -y install net-tools             112 MB              
585392f09407        54 minutes ago      /bin/sh -c yum -y install vim                   167 MB              
4aa136d65f26        About an hour ago   /bin/sh -c #(nop) WORKDIR /usr/local            0 B                 
2e09cdb61576        About an hour ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0 B                 
281446cb753d        About an hour ago   /bin/sh -c #(nop)  MAINTAINER bruceliu<bru...   0 B                 
9f38484d220f        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B                 
<missing>           3 months ago        /bin/sh -c #(nop)  LABEL org.label-schema....   0 B                 
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:074f2c974463ab3...   202 MB   

5.小结

在这里插入图片描述

原创文章 35 获赞 13 访问量 2342

猜你喜欢

转载自blog.csdn.net/Bankofli/article/details/105886523