Docker精华问答 | Docker commit如何用?

640?wx_fmt=png

Docker 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的维护效率,降低了云计算应用开发的成本!使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松!


640?wx_fmt=gif1

Q:Docker commit如何用?

 

A:简单的回答就是,不要用 commit,去写 Dockerfile。

Docker 不是虚拟机。这句话要在学习 Docker 的过程中反复提醒自己。所以不要把虚拟机中的一些概念带过来。Docker 提供了很好的 Dockerfile 的机制来帮助定制镜像,可以直接使用 Shell 命令,非常方便。而且,这样制作的镜像更加透明,也容易维护,在基础镜像升级后,可以简单地重新构建一下,就可以继承基础镜像的安全维护操作。

使用 docker commit 制作的镜像被称为黑箱镜像,换句话说,就是里面进行的是黑箱操作,除本人外无人知晓。即使这个制作镜像的人,过一段时间后也不会完整的记起里面的操作。那么当有些东西需要改变时,或者因基础镜像更新而需要重新制作镜像时,会让一切变得异常困难,就如同重新安装调试配置服务器一样,失去了 Docker 的优势了。

另外,Docker 不是虚拟机,其文件系统是 Union FS,分层式存储,每一次 commit 都会建立一层,上一层的文件并不会因为 rm 而删除,只是在当前层标记为删除而看不到了而已,每次 docker pull 的时候,那些不必要的文件都会如影随形,所得到的镜像也必然臃肿不堪。而且,随着文件层数的增加,不仅仅镜像更臃肿,其运行时性能也必然会受到影响。这一切都违背了 Docker 的最佳实践。

使用 commit 的场合是一些特殊环境,比如入侵后保存现场等等,这个命令不应该成为定制镜像的标准做法。所以,请用 Dockerfile 定制镜像。


640?wx_fmt=gif2

Q:为什么说不要使用 import, export, save, load, commit 来构建镜像?

 

A:commit 命令在前一个问答已经说过,这是制作黑箱镜像,无法维护,不应该被使用。

import 和 export 的做法,实际上是将一个容器来保存为 tar 文件,然后在导入为镜像。这样制作的镜像同样是黑箱镜像,不应该使用。而且这类导入导出会导致原有分层丢失,合并为一层,而且会丢失很多相关镜像元数据或者配置,比如 CMD 命令就可能丢失,导致镜像无法直接启动。

save 和 load 确实是镜像保存和加载,但是这是在没有 registry 的情况下,手动把镜像考来考去,这是回到了十多年的 U 盘时代。这同样是不推荐的,镜像的发布、更新维护应该使用 registry。无论是自己架设私有 registry 服务,还是使用公有 registry 服务,如 Docker Hub。


640?wx_fmt=gif3

Q:Dockerfile 怎么写? 

 

A:最直接也是最简单的办法是看官方文档。

这篇文章讲述具体 Dockerfile 的命令语法:https://docs.docker.com/engine/reference/builder/

然后,学习一下官方的 Dockerfile 最佳实践:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/

最后,去 Docker Hub 学习那些官方(Official)镜像 Dockerfile 咋写的。


640?wx_fmt=gif4

Q:Dockerfile 就是 Shell 脚本吧?

 

A:不是这样的。Dockerfile 不等于 .sh 脚本,Dockerfile 确实是描述如何构建镜像的,其中也提供了 RUN 这样的命令,可以运行 shell 命令。但是和普通 shell 脚本还有很大的不同。

Dockerfile 描述的实际上是镜像的每一层要如何构建,所以每一个RUN是一个独立的一层。所以一定要理解“分层存储”的概念。上一层的东西不会被物理删除,而是会保留给下一层,下一层中可以指定删除这部分内容,但实际上只是这一层做的某个标记,说这个路径的东西删了。但实际上并不会去修改上一层的东西。每一层都是静态的,这也是容器本身的 immutable 特性,要保持自身的静态特性。

所以很多新手会常犯下面这样的错误,把 Dockerfile 当做 shell 脚本来写了:

RUN yum update

RUN yum -y install gcc

RUN yum -y install python

ADD jdk-xxxx.tar.gz /tmp

RUN cd xxxx && install

这是相当错误的。除了无畏的增加了很多层,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。

正确的写法应该是把同一个任务的命令放到一个 RUN 下,多条命令应该用 && 连接,并且在最后要打扫干净所使用的环境。比如下面这段摘自官方 redis 镜像 Dockerfile 的部分:

RUN buildDeps='gcc libc6-dev make' \
&& set -x \
&& apt-get update && apt-get install -y $buildDeps --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* \
&& wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL" \
&& echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& rm redis.tar.gz \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps


640?wx_fmt=gif5

Q:那我把所有命令都合并到一个 RUN 就对了吧? 

 

A:不是把所有命令都合为一个 RUN,要合理分层,以加快构建和部署。合理分层就是将具有不同变更频繁程度的层,进行拆分,让稳定的部分在基础,更容易变更的部分在表层,使得资源可以重复利用,以增加构建和部署的速度。以 node.js 的应用示例镜像为例,其中的复制应用和安装依赖的部分,如果都合并一起,会写成这样:

COPY . /usr/src/app
RUN npm install

但是,在 node.js 应用镜像示例中,则是这么写的:

COPY package.json /usr/src/app/
RUN npm install
COPY . /usr/src/app

从层数上看,确实多了一层。但实际上,这三行分开是故意这样做的,其目的就是合理分层,充分利用 Docker 分层存储的概念,以增加构建、部署的效率。在 docker build 的构建过程中,如果某层之前构建过,而且该层未发生改变的情况下,那么 docker 就会直接使用缓存,不会重复构建。因此,合理分层,充分利用缓存,会显著加速构建速度。

第一行的目的是将 package.json 复制到应用目录,而不是整个应用代码目录。这样只有 pakcage.json 发生改变后,才会触发第二行 RUN npm install。而只要 package.json 没有变化,那么应用的代码改变就不会引发 npm install,只会引发第三行的 COPY . /usr/src/app,从而加快构建速度。而如果按照前面所提到的,合并为两层,那么任何代码改变,都会触发 RUN npm install,从而浪费大量的带宽和时间。合理分层除了可以加快构建外,还可以加快部署,要知道,docker pull 的时候,是分层下载的,并且已存在的层就不会重复下载。

比如,这里的 RUN npm install 这一层,往往会几百 MB 甚至上 GB。而在 package.json 未发生变更的情况下,那么只有 COPY . /usr/src/app 这一层会被重新构建,并且也只有这一层会在各个节点 docker pull 的过程中重新下载,往往这一层的代码量只有几十 MB,甚至更小。这对于大规模的并行部署中,所节约的东西向流量是非常显著的。特别是敏捷开发环境中,代码变更的频繁度要比依赖变更的频繁度高很多,每次重复下载依赖,会导致不必要的流量和时间上的浪费。


640?wx_fmt=png

小伙伴们冲鸭,后台留言区等着你!

关于Docker,今天你学到了什么?还有哪些不懂的?除此还对哪些话题感兴趣?快来留言区打卡啦!留言方式:打开第XX天,答:……

同时欢迎大家搜集更多问题,投稿给我们!风里雨里留言区里等你~


福利

1、扫描添加小编微信,备注“姓名+公司职位”,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!


640?wx_fmt=jpeg


推荐阅读:

  • IEEE 回应禁止华为系审稿人;WiFi联盟、蓝牙联盟已恢复华为成员资格;中国计算机学会:暂时中止与IEEE通信学会合作……

  • ARM 发布新一代 CPU 和 GPU,实现 20% 性能提升!

  • 前端开发 20 年变迁史

  • 北漂杭漂的程序员,是如何买到第一套房子?

  • “爱装X”开源组织:“教科书级”AI知识树究竟长什么样?

  • 500行Python代码打造刷脸考勤系统

  • 权游播完了, 你在骂烂尾, 有人却悄悄解锁了新操作……


640?wx_fmt=png真香,朕在看了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/523494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java channel源码_Netty 4.0 源码分析(三):Channel和ChannelPipeline

Client和server通过Channel连接,然后通过ByteBuf进行传输。每个Channel有自己的Pipeline,Pipeline上面可以添加和定义Handler和Event。Channel类1 package io.netty.channel;2 import io.netty.buffer.ByteBuf;3 import io.netty.buffer.MessageBuf;4 im…

一拍即合、一见钟情之后,智慧城市的“福利”来啦……

戳蓝字“CSDN云计算”关注我们哦!“未来双方的合作会针对智慧城市、智慧建筑以及智慧地域开发等领域开展创新型的解决方案,这种创造对于目前已经存在的,该领域技术甚至是竞争对手都是一个强大的震撼与颠覆。”达索系统董事会副主席兼首席执行…

Springboot部署到Tomcat,可以不带项目名进行访问

文章目录1. 进入tomcat的conf目录2. 编辑server.xml2.1. 修改第一处2.2. 修改第二处2.3. 发布war包2.4. 浏览器请求2.5. windows样例1. 进入tomcat的conf目录 cd /app/tomcat8081/conf/2. 编辑server.xml Tomcat9使用war包设置默认项目需要设置下server.xml就行 vim server.…

python ndarray append_9-Python-NumPy数组元素的添加与删除

数组元素的添加与删除 相关函数列表如下:函数元素及描述resize返回指定形状的新数组append将值添加到数组末尾insert沿指定轴将值插入到指定下标之前delete删掉某个轴的子数组,并返回删除后的新数组unique查找数组内的唯一元素1)返回指定大小的新数组num…

Java -jar 如何在后台运行项目

演示项目: GitHub链接:https://github.com/gb-heima/java-jar-nohup zip下载链接:https://github.com/gb-heima/java-jar-nohup/archive/master.zip git下载地址: git clone gitgithub.com:gb-heima/java-jar-nohup.git编译打包 …

裁员1700人,IBM 声称内部调整团队;谷歌将以26亿美元全现金收购Looker,绝对大手笔...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 贝索斯旗下蓝色起源将登月球…

修改Tomcat默认的端口

文章目录1. 进入/app/tomcat8081/conf,编辑server.xml文件2. 修改3个端口2.1. 第一个:停止端口,默认8005,修改为80062.2. 第二个:修改http访问端口,默认8080修改为80812.3. 第三个:修改APJ端口&…

Lambda 表达式有何用处?

戳蓝字“CSDN云计算”关注我们哦!我们知道,对于一个Java变量,我们可以赋给其一个“值”。如果你想把“一块代码”赋给一个Java变量,应该怎么做呢?比如,我想把右边那块代码,赋给一个叫做aBlockOf…

Java Web项目_order下载、运行

项目简介: order为GitHub开源项目,作为java web测试的参考项目,可以快速编译打包运行,UI设计采用bootstrap页面美观! 文章目录一、 order项目下载1.1. 项目链接:1.2. zip包下载链接:1.3. GitHub…

纯粹,极致!他用两个词阐释了UCloud

“我觉得有一个词是肯定的:纯粹,另一个词可能是极致。但这个词我有些犹豫,因为我们做的还不够好。”UCloud技术副总裁杨镭在UCloud用户大会期间接受老孙独家采访时这样形容UCloud。 UCloud技术副总裁杨镭关于UCloud:一家简单、纯粹…

java gc堆中的分区_jvm内存各个区域详解

内存区域划分Java虚拟机所管理的内存区域分为如下部分:方法区、GC堆、虚拟机栈、本地方法栈、PC程序计数器。其中方法区、GC堆是所有线程共享的;虚拟机栈、本地方法栈、PC程序计数器是各个线程独占的。image.pngPC程序计数器程序计数器可以看做是当前线程…

157 亿美元 !Salesforce 收购 Tableau !微软发布警告,表明黑客利用Office漏洞发动垃圾邮件攻击……...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 荣耀在成都的全球首家Life概…

Git 远程配置_03

文章目录1. 生成SSH key 认证证书2. 查看公钥3. 拷贝公钥的内容,并设置到github中远程配置就是怎样和远程仓库建立连接? 1. 在本地生成公钥和私钥(认证证书) 2. 把本地生成的公钥复制到远程仓库的ssh key中保存1. 生成SSH key 认证证书 ssh-keygen -t rsa -C &qu…

Jenkins修改管理员密码

Jenkins的加密方式 Jenkins 的密码采用的是Java加解密工具 jBCrypt,我也是第一次接触到这种加密方式,实在被他惊叹到了!这种加密方式每次加密同一个明文竟然都是得到不一样的结果,那他又是通过怎样的方式来解密的呢?原…

Storm精华问答 | 如何理解spout/bolt的生命周期?

戳蓝字“CSDN云计算”关注我们哦!Storm是Twitter开源的分布式实时大数据处理框架,被业界称为实时版Hadoop。随着越来越多的场景对Hadoop的MapReduce高延迟无法容忍,比如网站统计、推荐系统、预警系统、金融系统等, 大数据实时处理…

刚刚!6月榜单:JS跌惨,Python又霸榜,C++再无翻身可能!

Python勇者无敌!最近一份PYPL 6月报告了来了,通过半年的发展,Python基本已奠定2019年-2020的地位,持续称王就对了!PLPY 6月榜单,JS跌惨只见Python笑,哪闻C哭PYPL 发布 6 月编程语言指数榜啦。毫…

java vector 输出_5.7(java学习笔记)Vector、Enumeration

一.VectorVector类实现一个可扩展的数组对象。与数组一样,它包含可以使用整数索引访问。它的基本操作方法add(int index, E element),get(int index),indexOf(Object o)等操作方法与数组中的方法类似这里就不叙述了。我们主要看一个方法&…

企业实战案例01_Jenkins_连接远程执行shell脚本

文章目录一、Jenkins 远程连接执行shell脚本1.1. 新建节点1.2. 配置节点信息二、连接远程验证测试2.1. 创建任务2.2. 添加注释2.3. 设置最大构建数量2.4. 限制项目的运行节点2.5. 选择构建环境2.6. 填写获取Tomact目录列表脚本2.7. 立即构建项目2.8. 查看控制台日志监控一、Jen…

纯粹,极致!他用两个词阐释了UCloud | 人物志

戳蓝字“CSDN云计算”关注我们哦!“我觉得有一个词是肯定的:纯粹,另一个词可能是极致。但这个词我有些犹豫,因为我们做的还不够好。”UCloud技术副总裁杨镭在UCloud用户大会期间接受老孙独家采访时这样形容UCloud。UCloud技术副总…

企业实战案例02_Jenkins_连接远程GitLab拉取代码

编译、打包 文章目录一、任务新建和配置信息1. 新建任务2. 添加描述3. 设置构建的最大数量4. 添加Git构建参数5.复制远程项目链接地址6. 粘贴远程项目地址7. 添加凭据7. 要编译的分支8. 效果图9. 编译和打包项目二、构建项目和日志监听1. 查看工作区(构建项目前&…