转载请注明出处 https://www.cnblogs.com/majianming/p/9536975.html

在每执行一个命令时,便会commit形成一个层,最后形成堆栈式的结构。最后的镜像是各个分层按照顺序堆叠起来的结果。

其中镜像层的内容并不能被之后的命令修改,也就是一个层的文件都是只读的,如果需要修改文件,那么只是在顶端添加一层,然后在最上一层添加修改之后的文件,并对上层屏蔽修改之前的文件,修改之前的文件仍然原样存在原本的层中。

比如接下来的场景,使用了wget下载了nginx并解压(忽略编译等步骤),然后删除

RUN wget --no-check-certificate -O /tmp/nginx-1.15.2.tar.gz http://nginx.org/download/nginx-1.15.2.tar.gz
RUN cd /tmp/ && tar zxf nginx-1.15.2.tar.gz
RUN rm nginx-1.15.2.tar.gz

原本看起来没有什么不正确,先看nginx-1.10.2.tar.gz,解压后的压缩文件应该删除是没有错的,但是按照上面说的,这样的删除实际上是没有用的,只是层镜像屏蔽了对这个文件的可见性而已,这个文件还是存在于上层镜像,所以最后的镜像大小并不会因为执行了这个命令而减少。

(D 表示delete,删除; A表示add,添加;C表示change,修改)

上图也说明了一点,如果尝试删除镜像中已经存在的文件,因为文件实际上并没有被删除,只是被屏蔽致使上层不可见,所以并不会减少镜像的大小(还可能增大,什么时候会可能增大?因为删除过程中还可能修改了其他文件,那么这些被修改的文件需要复制一份到顶层,然后修改,而原来的镜像文件并没有变化)

那么反正没有用,我们不删除?

这个也是不对的,在构建过程中,要随手删除产生的额外文件,这里并没有和上面所说的矛盾,准确来说是在同一个命令中删除无用的文件。那么上面的命令应该改为

RUN wget –no-check-certificate -O /tmp/nginx-1.10.2.tar.gz http://nginx.org/download/nginx-1.10.2.tar.gz && cd /tmp/ && tar zxf nginx-1.10.2.tar.gz && rm nginx-1.10.2.tar.gz

这样这个命令执行完毕时,commit形成的新的镜像也就不会存在nginx-1.10.2.tar.gz,同理,在nginx编译过程中会产生许多的中间文件,为了保证最后的镜像的最小,也需要在同一个命令中删除文件。

上面提到了对于dockerfile的每一个命令都会自动commit形成,如果使用aufs文件系统,会受到42层的限制,所以按照这个理论应该减少层的形成,但是应该与以下情况相权衡

如果是在docker镜像中编译java文件,那么常常会出现以下的情况

# 拷贝文件
COPY . /opt/`
# 执行构建
RUN mvn clean package

这样的话,在执行构建的情况下,会依照pom文件下载相应的依赖库,但是在很多情况下这些依赖库是不会改变的,所以可以缓存起来,所以可以先复制pom文件,然后下载相应的依赖,再复制容易改变的源代码等文件后进行构建,充分利用缓存

COPY pom.xml /opt/
RUN mvn verify clean --fail-never -f /opt/pom.xml
COPY src/ /opt/src
RUN mvn clean package

参考

AUFS https://coolshell.cn/articles/17061.html

aufs wiki https://zh.wikipedia.org/wiki/Aufs

docker 存储驱动 https://docs.docker.com/storage/storagedriver/select-storage-driver/#supported-storage-drivers-per-linux-distribution

docker 实战(docker in action中文版)

aufs文件系统的42层限制 https://stackoverflow.com/questions/39382518/whats-the-reason-for-the-42-layer-limit-in-docker

联合文件系统 https://yeasy.gitbooks.io/docker_practice/underly/ufs.html

转载请注明出处 https://www.cnblogs.com/majianming/p/9536975.html

dockerfile构建的镜像的更多相关文章

  1. 使用dockerfile构建nginx镜像

    使用dockerfile构建nginx镜像 docker构建镜像的方法:   commit.dockerfile 1.使用commit来构建镜像: commit是基于原有镜像基础上构建的镜像,使用此方 ...

  2. Dockerfile构建私有镜像

    构建第一个镜像 镜像的定制实际上就是定制每一层所添加的配置,文件.我们可以把每一层修改,安装,构建,操作的命令都写入一个脚本,这个脚本就是Dockerfile.Dockerfile是一个文本文件,其内 ...

  3. Dockerfile构建jar镜像

    dockerDockerfilejar包docker-compose 一.安装docker和compose 二.准备jar包 三.编写配置文件 1. Dockerfile 2. docker-comp ...

  4. Dockerfile构建nginx镜像

    Dockerfile构建nginx镜像 [root@bogon ~]# mkdir /opt/docker-file [root@bogon ~]# cd /opt/docker-file/ [roo ...

  5. Docker学习(六)Dockerfile构建自定义镜像

    Docker学习(六)Dockerfile构建自定义镜像 前言 通过前面一篇文章可以知道怎么去使用一个镜像搭建服务,但是,如何构造自己的一个镜像呢,docker提供了dockerfile可以让我们自己 ...

  6. dockerfile构建Tomcat镜像

    dockerfile构建Tomcat镜像 一.镜像分层概念 二.制作tomcat镜像 2.1.创建分层目录 [root@node2 ~]# mkdir /app/{web/{nginx,tomcat, ...

  7. Docker 使用Dockerfile构建redis镜像

    Dockerfile实现: FROM centos: MAINTAINER hongdada "hongdaqi159505@gmail.com" WORKDIR /home RU ...

  8. Docker 使用Dockerfile构建tomcat镜像

    Dockerfile概念: 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那么之前提及的无法重复的问题. ...

  9. 如何使用Dockerfile构建Tomcat镜像并部署war

    我们都知道Docker构建一个镜像有两种方式: 使用`docker commit`命令 使用`Dockerfile`文件和`docker build`命令 那么这两种方式有何区别呢? 相同点:底层实现 ...

  10. 使用dockerfile构建nginx镜像 转

      docker构建镜像的方法:   commit.dockerfile 1.使用commit来构建镜像: commit是基于原有镜像基础上构建的镜像,使用此方法构建镜像的目的:保存镜像里的一些配置信 ...

随机推荐

  1. #define中的#和##作用

    #define语句中的#是把参数字符串化,##是连接两个参数成为一个整体. #define FACTORY_REF(name) { #name, Make##name } 中#name就是将传入的na ...

  2. Python 点滴 I

    [为什么使用Python] 1. 软件质量:   Python更注重软件质量,一致性,可维护性 2. 开发效率:   相比C/C++/Java这些编译/静态语言,无需编译及链接步骤,Python所须要 ...

  3. android 自己主动拒接后再取消自己主动拒接,该联系人来电界面无图标显示,且点击挂断无反应

    1.    设置一个联系人为自己主动拒接 2.    该联系人来电 3.    取消该联系人的自己主动拒接 4.    该联系人来电 Error: 来电界面无头像显示,直接显示黑屏,且点击拒接butt ...

  4. Camera 模组

    http://wenku.baidu.com/view/89d8c21014791711cc7917d5.html http://wenku.baidu.com/view/0cec54d5c1c708 ...

  5. iOS音频播放 (四):AudioFile 转

    原文出处 : http://msching.github.io/blog/2014/07/19/audio-in-ios-4/ 前言 接着第三篇的AudioStreamFile这一篇要来聊一下Audi ...

  6. Sql数据库查询语言

    1.概述 Sql是一种面向数据库的结构化查询语言.是符合美国国家标准化组织ANSI的一种计算机标准语言. Sql具对数据库的操作有:增删改查.创建数据库.创建表.创建存储过程.创建视图等 RDBMS关 ...

  7. HBase 数据迁移

    最近两年负责 HBase,经常被问到一些问题, 本着吸引一些粉丝.普及一点HBase 知识.服务一点阅读人群的目的,就先从 HBase 日常使用写起,后续逐渐深入数据设计.集群规划.性能调优.内核源码 ...

  8. su: /bin/bash: Permission denied带来的疑惑

    >客户一个oracle突然当机了,由于业务启动,客户下意识的重启了服务器,系统是起来了,准备切换到oracle用户下启动数据库,可以怎么都无法su切换,真是火上浇油呀,描述如下: 在root用户 ...

  9. C中使用memset

    int i; cout<<memset(&i,1,sizeof(int))<<endl; 输出结果是16843009,而不是填充的1111 1111,为什么呢? 因为m ...

  10. (5)在tomcat运行自己的javaweb项目

    A:在MyEclipse下方的Servers栏中启动服务器,运行项目: 1,选中项目所在的tomcat服务器 2,点击“启动按钮”,见下图 3,启动以后,看控制台输出日志: B:从服务器按钮启动: 1 ...