当前位置:   article > 正文

Docker学习(7)——常用的两种构建镜像方式的基础知识_docker学习 构建镜像

docker学习 构建镜像

本文参考了一下别人的博客,在网上查了一些知识

1.镜像的基础知识

镜像是一种文件结构,包含如何运行容器的元数据
Dockerfile中的每条命令都会在文件系统中创建一个新的层次结构
文件系统在这些层次上构建起来,镜像就构建于这些联合的文件系统之上
当容器启动后,所有镜像都会统一合并到一个进程中
联合文件系统中的文件被删除时, 它们只是被标记为已删除,但实际上仍然存在

2.镜像的分层结构

共享宿主机的kernel
base镜像提供的是最小的Linux发行版
同一docker主机支持运行多种Linux发行版
采用分层结构的最大好处是:共享资源
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

Copy-on-Write 可写容器层
容器层以下所有镜像层都是只读的
docker从上往下依次查找文件
容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
一个镜像最多127层
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

3.两种常用的构建镜像的方式

  • (1)两种方式构建镜像的主要步骤:

从容器构建镜像(以下简称容器镜像)——commit命令

创建一个容器,比如使用 tomcat:latest 镜像创建一个tomcat-test容器
修改tomcat-test容器的文件系统,比如修改tomcat的server.xml文件中的默认端口
使用commit命令提交镜像
  • 1
  • 2
  • 3

使用Dockerfile构建镜像(以下简称Dockerfile镜像)

编写Dockerfile文件
 使用build命令构建镜像
  • 1
  • 2
  • (2)两种构建方式的区别:

容器镜像的构建者可以任意修改容器的文件系统后进行发布,这种修改对于镜像使用者来说是不透明的,
镜像构建者一般也不会将对容器文件系统的每一步修改,记录进文档中,供镜像使用者参考。
容器镜像不能(更准确地说是不建议)通过修改,生成新的容器镜像。

从镜像运行容器,实际上是在镜像顶部上加了一层可写层,所有对容器文件系统的修改,都在这一层中进行,不影响已经存在的层。
比如在容器中删除一个1G的文件,从用户的角度看,容器中该文件已经没有了,但从文件系统的角度看,文件其实还在,
只不过在顶层中标记该文件已被删除,当然这个标记为已删除的文件还会占用镜像空间。
从容器构建镜像,实际上是把容器的顶层固化到镜像中。

也就是说, 对容器镜像进行修改后,生成新的容器镜像,会多一层,而且镜像的体积只会增大,不会减小。
长此以往,镜像将变得越来越臃肿。Docker提供的 export 和 import 命令可以一定程度上处理该问题,但也并不是没有缺点。

容器镜像依赖的父镜像变化时,容器镜像必须进行重新构建。
如果没有编写自动化构建脚本,而是手工构建的,那么又要重新修改容器的文件系统,再进行构建,这些重复劳动其实是没有价值的。

Dockerfile镜像是完全透明的,所有用于构建镜像的指令都可以通过Dockerfile看到。
甚至你还可以递归找到本镜像的任何父镜像的构建指令。
也就是说,你可以完全了解一个镜像是如何从零开始,通过一条条指令构建出来的。
Dockerfile镜像需要修改时,可以通过修改Dockerfile中的指令,再重新构建生成,没有任何问题。

Dockerfile可以在GitHub等源码管理网站上进行托管,DockerHub自动关联源码进行构建。
当你的Dockerfile变动,或者依赖的父镜像变动,都会触发镜像的自动构建,非常方便。

通过上面的简单介绍你应该也会感觉使用Dockerfile构建镜像的方式相对来说会更加适用。
接下来我们来说说使用Dockerfile时会用到的相关参数

4.Dockerfile语法

Dockerfile由一系列指令和参数组成。每条指令都必须为大写字母,并且后面要跟随一个参数
Dockerfile中的指令会按照顺序从上到下执行,所以应该根据需要合理安排指令的顺序
每条指令都会创建一个新的镜像层并对镜像进行提交
Docker大体上按照如下流程执行Dockerfile中的指令

Docker从基础镜像运行一个容器。
执行第一条指令,对容器进行修改。
执行类似docker commit的操作,提交一个新的镜像层。
Docker再基于刚提交的镜像运行一个新的容器。
执行Dockerfile中的下一条命令,直到所有指令都执行完毕。
  • 1
  • 2
  • 3
  • 4
  • 5

Dockerfile也支持注释,以#开头的行都会被认为是注释

参数详解
FROM每个Dockerfile的第一条指令都应该是FROM。FROM指令指定一个已经存在的镜像,后续指令都是将基于该镜像进行,这个镜像被称为基础镜像(base iamge)。在这里ubuntu:latest就是作为新镜像的基础镜像。也就是说Dockerfile构建的新镜像将以ubuntu:latest操作系统为基础。在运行一个容器时,必须要指明是基于哪个基础镜像在进行构建。
MAINTAINERMAINTAINER指令,这条指令会告诉Docker该镜像的作者是谁,以及作者的邮箱地址。这有助于表示镜像的所有者和联系方式
RUN在这些命令之后,RUN指令会在当前镜像中运行指定的命令。这里我们通过RUN指令更新了APT仓库,安装nginx包,并创建了一个index.html文件。像前面说的那样,每条RUN指令都会创建一个新的镜像层,如果该指令执行成功,就会将此镜像层提交,之后继续执行Dockerfile中的下一个指令。默认情况下,RUN指令会在shell里使用命令包装器/bin/sh -c 来执行。如果是在一个不支持shell的平台上运行或者不希望在shell中运行(比如避免shell字符串篡改),也可以使用exec格式的RUN指令,通过一个数组的方式指定要运行的命令和传递给该命令的每个参数:RUN [“apt-get”, “install”, “-y”, “nginx”]
EXPOSEEXPOSE指令是告诉Docker该容器内的应用程序将会使用容器的指定端口。这并不意味着可以自动访问任意容器运行中服务的端口。出于安全的原因,Docker并不会自动打开该端口,而是需要你在使用docker run运行容器时来指定需要打开哪些端口。可以指定多个EXPOSE指令来向外部公开多个端口,Docker也使用EXPOSE指令来帮助将多个容器链接。
COPY把文件从build context复制到镜像,支持两种形式:COPY src dest 和 COPY [“src”, “dest”],src必须指定build context中的文件或目录
ADD用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像:ADD html.tar /var/www
ENV设置环境变量,变量可以被后续的指令使用:ENV HOSTNAME sevrer1.example.com
WORKDIR为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。
CMD 与 ENTRYPOIN这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。docker run后面的参数可以传递给ENTRYPOINT指令当作参数。Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/73896
推荐阅读
相关标签
  

闽ICP备14008679号