企业版Docker<6>——常用的两种构建镜像方式(Dockerfile、commit)的基础知识

一、镜像的基础知识

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

二、镜像的分层结构

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

在这里插入图片描述

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

在这里插入图片描述
三、两种常用的构建镜像的方式

  • (1)两种方式构建镜像的主要步骤:
    从容器构建镜像(以下简称容器镜像)——commit命令
 创建一个容器,比如使用 tomcat:latest 镜像创建一个tomcat-test容器
修改tomcat-test容器的文件系统,比如修改tomcat的server.xml文件中的默认端口
使用commit命令提交镜像

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

编写Dockerfile文件
使用build命令构建镜像
  • (2)两种构建方式的区别:
容器镜像的构建者可以任意修改容器的文件系统后进行发布,这种修改对于镜像使用者来说是不透明的,镜像构建者一般也不会将对容器文件系统的每一步修改,记录进文档中,供镜像使用者参考。容器镜像不能(更准确地说是不建议)通过修改,生成新的容器镜像。
从镜像运行容器,实际上是在镜像顶部上加了一层可写层,所有对容器文件系统的修改,都在这一层中进行,不影响已经存在的层。

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

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

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

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

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

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

四、Dockerfile语法

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

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

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

参数详解
FROM每一条Dockerfile的每一条指令都应该是FROM。FROM指令指定一个已经存在的镜像,后续指令都是将基于该镜像进行,这个镜像被称为基础镜像(base image) 。在这里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指令,通过一个数组的方式指定要运行的命令和传递给该i命令的每个参数;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 server1.example.com
WORKDIR为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创键
CMD与ENTRYPOINT这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令所覆盖,而ENTRYPOINT不会被覆盖,一定会被执行。docker run后面的参数可以传递给ENTRYPOINT指令当作参数。Dockerfile中只能指定一个ENTRYPOINT,若指定很多,如果有多个为ENTRYPOINT指令则以最后一个为准;

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值