Docker 学习篇(六)

程序媛和她的猫

共 6688字,需浏览 14分钟

 · 2021-09-26

1、数据卷容器
(1)数据卷容器和容器数据卷

在上一节,我们讲了何为容器数据卷,当我们使用 docker run -it -v /主机绝对路径目录:/容器内目录 镜像名,-v 就是创建一个容器的数据卷,它的作用是把容器内的数据持久化到宿主机上,当容器内数据发生变化,宿主机相应位置的数据也会发生变化。

有两个容器 dc01 和 dc02,我们使用 dc02 volume-from dc01 这个命令,就可以实现容器1和容器2之间的数据共享,类似于一种继承关系,数据卷容器就是被 volume-from 的那个容器,即 dc01。

(2)举个例子来讲解数据卷容器

1、运行我们创建的新镜像 zhouxuejiao/centos 生成一个容器,命名为 dc01,docker run -it --name dc01 zhouxuejiao/centos。

图1

在 dc01 内部的容器数据卷 dataVolumeContainer2 中在增加一个文件 dc01_add.txt。

图2

2、退出 dc01 容器,只退出,不停止运行,使用 Ctrl+P+Q。

3、让 dc02 和 dc03 分别继承 dc01,

docker run -it --name dc02 --volumes-from dc01 zhouxuejiao/centos
docker run -it --name dc03 --volumes-from dc01 zhouxuejiao/centos

此时 dc02 和 dc01 可以实现数据的共享,dc03 和 dc01 可以实现数据的共享,dc02 和 dc03 也可以实现数据的共享(因为 dc02 和 dc03 都继承自 dc01,dc01 相当于一个中介,所以 dc02 和 dc03 也可以实现数据的共享)。

4、此时提出一个问题,当我们删除父容器 dc01,dc02 和 dc03 还可以进行数据的互享吗?

答案是可以的,删除父容器 dc01 后,dc02 和 dc03 仍然存在且可以进行数据共享。这是因为容器之间信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

2、DockerFile
(1)DockerFile 是什么?

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

(2)DockerFile 构建的三步骤

第一步:编写。手动编写一个 DockerFile 文件,必须符合 DockerFile 的规范。

第二步:构建。有了 DockerFile 文件后,直接执行 docker build DockerFile 这个命令,即可获得一个自定义的镜像。

第三步:运行。使用 docker run 运行上一步得到的镜像。

(3)DockerFile 文件长什么样?

以 centos 镜像的 DockerFile 文件为例,见图3,我们来看一下 DockerFile 文件长什么样。

图3

scratch:所有镜像的父镜像,类似于Java中的Object是所有类的根父类。
MAINTAINER:作者及邮箱。
LABEL:说明。

(4)编写 DockerFile 的规范

(1)每条保留字指令都必须为大写字母,且后面跟随至少一个参数,以FROM scratch为例,FROM就是保留字指令,其后面必须跟一个参数,即scratch,否则会报错,dockerfile的语法有问题。
(2)指令按照从上到下,顺序执行。
(3)#表示注释。
(4)每条指令都会创建一个新的镜像层(之前讲过,镜像是分层的),并对镜像进行提交。

(5)实际开发部署场景中,DockerFile 是如何使用的?

首先开发人员将要部署的程序编写到 DockerFile 中,并将其 build 成一个镜像,然后开发人员将镜像交给运维人员,最后运维人员运行镜像,生成容器实例,此时程序就开始提供服务了。

(6)DockerFile 保留字指令

FROM:当前编写这个镜像是基于哪个镜像创建的,即它的父镜像是谁

MAINTAINER:镜像维护者的姓名和邮箱

RUN:容器构建过程中需要执行的一些命令,类似于java程序中的System.ou.println,java中是会打印到控制台,DockerFile 运行的时候,这些语句也会打印在命令行界面里。

EXPOSE:该镜像变成容器以后,对外暴漏的接口,比如 centos 的默认端口是 6379,见图4。

图4

WORKDIR:运行镜像成为一个容器,登录容器终端直接进入到的目录。以下面的centos为例,容器终端直接进入的是容器的根目录/,见图5。

图5

ENV:用来在构建镜像的过程中设置环境变量。比如

ENV MY_PATH /usr/mytest // 定义环境变量 MY_PATH,其值为 /usr/mytest
WORKDIR $MY_PATH // 引用上面定义的环境变量,引用时环境变量前面需要加上$,这句话等价于 WORKDIR /usr/mytest

ADD:拷贝文件或目录进镜像,ADD 命令不仅仅会拷贝,还会解压 tar 压缩包。以 centos 的 DockerFile 为例,它拷贝并解压 docker.tar 到镜像中。

图6

COPY:类似ADD,拷贝文件和目录到镜像中,但是它只是拷贝,不会解压 tar包。COPY 将从构建上下文目录中<源路径>的文件复制到新的一层的镜像内的<目标路径>位置。它的使用方法有两种:COPY src test和COPY ["src","dest"]。

VOLUME:容器数据卷,用于数据保存和持久化工作

CMD:指定一个容器启动时要运行的命令,比如 centos 中的 CMD ["/bin/bash"] 相当于 docker run -it centos /bin/bash。DockerFile 中可以有多个 CMD 指令,但只有最后一个生效,比如CMD ["/bin/bash"] CMD cat /etc/hosts,最后cat /etc/hosts 会覆盖 /bin/bash。

ENTRYPOINT:指定一个容器启动时要运行的命令,功能与 CMD 一样,和 CMD 不同的是,当有多条 ENTRYPOINT 指令时,不会出现覆盖,而是追加执行。

ONBUILD:父镜像在被子镜像继承的时候,父镜像 DockerFile 中的 ONBUIL 命令会被触发执行

接下来我们将用下面的几个案例,对这几个保留字进行说明。

3、自定义镜像 mycentos
(1)、编写 DockerFile

阿里云上拉取下来的 centos,进入容器的默认路径是/,且不支持 vim 和 ifconfig 命令。

我们来自定义一个 mycentos 使其具备如下特性:进入容器的默认路径不再是根目录,而是 /usr/local 目录,支持vim编译器,支持ifconfig查看网络配置。

DockerFile如下:

FROM centos // 我们以本地的 centos 为父镜像,增加一些功能,形成新镜像 mycentos。
MAINTAINER zhoxuuejiao<happy_girl@163.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH // 进入容器默认目录是 /usr/local

RUN yum -y install vim
RUN yum -y install net-tools // RUN 容器构建时执行的命令,所以我们让容器运行时,安装 vim 编译器、网络查看工具

EXPOSE 80 // 向外暴漏 80 端口

CMD echo $MYPATH
CMD echo "success.............ok" // 打印
CMD /bin/bash
图7
图8
(2)、根据 DockerFile 构建镜像,docker build -f /mydocker/Dockerfile -t mycentos .

构建过程的日志见图9至图15。

图9
图10
图11
图12
图13
图14
图15

构建完成,使用 dcoker images 查看所有镜像,发现 mycentos 镜像的镜像 ID 和日志中(图15)的一样。

图16
(3)、运行 mycentos 镜像,得到 mycentos 容器

此时,进入容器的默认路径是我们在 Dokcerfile 中指定的 /usr/local,见图17。

图17

此时,在容器中可以使用 vim 编译器,见图18、19,vim test.txt,创建并编译 test.txt 这个文件。

图18
图19

此时,使用 ifconfig 查看网络信息,也是可以的,见图20。

图20

至此,我们使用 DockerFile 创建 mycentos 镜像,创建成功。

(4)、查看镜像的创建历史。

docker histor 镜像ID,见图21,首先根据 centos 生成一个 base 镜像,然后每执行一句 DockerFile 中的指令,就会产生一个新的镜像,包裹在前面生成的镜像的外面,再次验证了镜像的分层结构。

图21
4、DockerFile 中的 CMD 和 ENTRYPOINT 指令

通过上一个案例,我们大致了解了一部分保留字指令,但是对于 CMD 和 ENTRYPOINT 还不是很了解,现在我们通过一个案例来讲解一下这两个保留字。

(1)、二者的共同点

CMD 和 ENTRYPOINT,都是指定一个容器启动时要运行的命令。

(2)、二者的不同点

1、CMD:DockerFile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换。

使用一个案例,来解释 “CMD 会被 docker run 之后的参数替换”,这句话是什么意思?

当我们执行 docker run -it -p 7777:8080 tomcat 这条命令启动 tomcat 时,tomcat 之所以能够正常启动,完全是因为其 DockerFile 最后一行的 CMD ["catalina.sh", run]。

如果我们改一下启动命令,docker run -it -p 7777:8080 tomcat ls -l,就相当于在 DockerFile 最后加了一条指令 CMD ls -l,它会覆盖掉 CMD ["catalina.sh", run],导致 tomcat 启动不起来。这就是 CMD 会被 docker run 之后的参数替换。

图22

2、ENTRYPOINT:功能与 CMD 一样,和 CMD 不同的是,当有多条 ENTRYPOINT 指令时,不会出现覆盖,而是追加执行。docker run 之后的参数会被当做参数传给 ENTRYPOINT,之后形成新的命令组合。

使用一个案例来解释,“docker run 之后的参数会被当做参数传给 ENTRYPOINT,之后形成新的命令组合”,这句话是什么意思?

首先我们使用 CMD 编写 DockerFile 制作一个可以查询百度网站首页的容器。

FROM centos
RUN yum install -y curl // 下载 curl 工具,curl 可以用来访问网址,使用 curl http://www.baidu.com,即可获得百度网站首页的信息。
CMD ["curl", "-s", "https://www.baidu.com"] // crul https://www.baidu.com,访问百度网站首页。
图23
图24

然后根据 DockerFile 构建镜像,docker build -f /mydocker/Dockerfile1 -t mybaidu . 。

图25

最后,运行这个就镜像,访问百度网站首页。docker run -it mybaidu。

图26

现在我们想要不光返回百度首页信息,还希望显示 HTTP 请求的头信息,此时就需要加上 -i 参数。docker -it mybaidu -i,这样运行是会失败的,因为 DockerFile 用的是 CMD,加上这个 -i 参数,就相当于在 DockerFile 莫问加上了 CMD -i,它就把 CMD ["curl", "-s", "https://www.baidu.com"] 这最重要的一句覆盖了,自然失败了。

图27

那应该怎么办呢?答案是使用 ENTRYPOINT,因为它不会覆盖,而是追加执行。来我们修改 Dockerfile。

FROM centos
RUN yum install -y curl 
ENTRYPOINT ["curl", "-s", "https://www.baidu.com"] 
图28
图29

构建镜像,docker build -f /mydocker/Dockerfile2 -t mybaidu2 . 。

图30

运行这个镜像,访问百度网站首页,并且在运行命令后加上参数 -i,获取 HTTP 头信息。docker run -it mybaidu2 -i。这就相当于在 DockerFile 末尾增加一句 ENTRYPOINT -i,因为 ENTRYPOINT 追加执行,所以不会有任何影响。

图31
图32
(9)DockerFile 中的 ONBUILD 指令

ONBUILD 指令:父镜像在被子镜像继承的时候,父镜像 DockerFile 中的 ONBUIL 命令会被触发执行。

使用一个案例,讲解 ONBUILD 这个指令。

首先制作父镜像 mybaidu_father,DockerFile 如下:

FROM centos
RUN yum install -y curl 
ENTRYPOINT ["curl", "-s", "https://www.baidu.com"]
ONBUILD RUN echo "father images onbuild--------666"
图33
图34

构建父镜像,docker build -f /mydocker/Dockerfile3 -t mybaidu_father .。

图35

然后我们制作子镜像 mybaidu_son,DockerFile 如下:

FROM mybaidu_father // 指定其父镜像为 mybaidu_father
RUN yum install -y curl 
ENTRYPOINT ["curl", "-s", "https://www.baidu.com"]
图36
图37

构建子镜像,docker build -f /mydocker/Dockerfile4 -t mybaidu_son .。

注意注意啦,当我们构建子镜像的时候,会触发父镜像中的 ONBUILD 指令,图38是构建子镜像的过程日志,红色框内就是在触发父镜像中的 ONBUILD 指令。

图38


浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报