Docker镜像原理和最佳实践

镜像

传统企业是以交付应用的方式进行发布的,交付应用相当于可执行性程序,其整个应用与环境是分开维护的。随着容器技术的兴起,提出了交付环境的概念。交付环境与交付应用相比,交付的不仅是可执行程序,还交付可执行程序依赖的配置文件、类库甚至是整个文件系统。在Docker语境里面,环境就是镜像。从上图左下角镜像示例图可以看出,镜像本身的组织结构是分层的。其优点是,虽然它包含了所有的依赖,但是发布部署的时候不会显著增加信息的传输量。

镜像的表示分为四部分:红色的部分是镜像中心域名,黄色的部分是镜像命名空间,我们可以根据命名空间进行权限控制等操作,绿色是镜像的名称,每个镜像有一个版本(即标签)。Docker官方的镜像不需要镜像中心的域名,有一些镜像可以省略命名空间。

镜像基本操作


镜像制作——Dockerfile

第一行是一个FROM指令,使用了一个叫alpine的基础镜像。所有的镜像都可以用来做基础镜像,我们通常不需要关心最基础的镜像是怎么来的,只需要在现有镜像的基础上,构建新的镜像即可。我们在构建的时候,Docker依赖这个基础镜像,在这个基础镜像之上我们再做一些改动,生产新的镜像。FROM指令必须要有,而且只能有一个,通常是放在整个Dockerfile的最前面。

RUN指令做的是在镜像里安装一些软件,或者做一些需要的操作。Docker RUN之后执行了Shell指令,它对镜像里面的内容做了一些改动,最后再执行Docker COMMIT,把当前容器里面的改动持久化到镜像里面。RUN命令可以执行多次。但是通常来说建议把需要的指令都写在一条RUN命令里面,用&&符号连接起来,好处是镜像只增加了一层,可以加快镜像构建的速度,减少镜像的层次。

在讨论ADD指令前,我们先看看构建命令的输入。构建命令的输入内容包括两项,第一项是Dockerfile,另一项是Dockerfile依赖的上下文目录。第一条ADD命令就是相当于把www目录从上下文目录拷贝到镜像目录下面,目录名是相同的。第二条ADD的命令是添加文件到镜像,还有一个类似的命令是COPY,ADD命令与COPY命令做的事情是一样的。但是ADD命令能做的更多,比如,你的源不一定是Dockerfile上下文目录里面的内容,可以是一个网络路径。ADD命令还能将可识别的压缩文件进行解压,然后再放到镜像里面。

EXPOSE命令,相当于告诉Docker的守护进程,当前这个镜像在运行变成一个容器的时候,其监听的端口是什么,上图中其监听的是80端口。这样声明出去,其他与当前容器在同一个网络里面的容器可以通过这个端口来访问这个当前容器。这个地方其实并没有指定主机的端口,主机端口需要在启动容器的时候,再具体指定。

CMD命令会做两件事情,但需要依赖一些前提条件,比如上图中做的事情是指定了镜像运行时候的首进程。

CMD指定首进程的方式有两种。一种是shell方式,以上图这种方式来指定可执行文件及其参数,实际上它的首进程会先启动一个shell进程,然后再将可执行文件及它的参数作为shell进程的参数传进去再启动。另外一种方式叫exec方式,它会把这些参数用方括号括起来,看上去是一个列表。这种启动方式的首进程就不是shell,而是可执行文件本身。

CMD命令与ENTRYPOINT命令有什么区别?如果CMD命令和ENTRYPOINT命令中有一个没有指定任何命令的话,实际上剩下的那个就是具体指定容器首进程的命令。但是如果两个命令同时存在,整个容器起来的首进程又是怎么指定呢?比如,现在指定了一个ENTRYPOINT命令,它有一个可执行文件,然后指定了可执行文件的参数。它生成这个首进程的话,就是刚刚提到的是以shell方式起来的,所以它解释出来的话,前面会加一个shell命令,然后再紧跟可执行文件,然后再跟上可执行文件的参数。如果在指定了ENTRYPOINT命令的同时又指定了这个CMD命令, CMD命令也有一个可执行文件及其参数。最后其效果是,在指定了ENTRYPOINT的情况下,如果有CMD命令,那么直接加在ENTRYPOINT命令后面,当作它的参数。整个这一串是作为首进程的指令起动起来的。

镜像优化

减小镜像大小

比如很常见的一个需求——镜像太大了。我们之前交付的是应用,通常一个可执行文件,它本身是很小。但是整个镜像如果太大的话,它整个传输过程中会增加部署的时间。减小镜像大小有几种方式:

使用轻量发行版的基础镜像。然后这个地方典型代表就是alpine的发行版。目前Docker的官方镜像基本都有一个基于alpine发行版制作的版本。其实我们在选择某一个基础镜像的时候会考量很多;

清理不必要的安装包和临时文件。在传输过程中,不同镜像大小的传输速度差别很明显。

加快镜像构建速度

现在应用的发布需求可能越来越多,比如说一天要发布很多次。我们在做镜像构建的时候,最常用的一个操作就是下载软件包去安装。所以我们推荐用国内的镜像软件源下载,比如使用阿里云的软件源进行下载。

构建使用缓存的条件包括:父层信息没有发生变化;当前构建指令没有变化;当前指令依赖的本地上下文没有发生变化。

镜像常见问题

唯一识别某个镜像

比如,一个Dockerfile构建了,推到了仓库,但是从仓库拉下来的时候,怎么知道拉到本地去部署的就是推上去的那个呢?所以说需要有一个标识来唯一识别某一个镜像。可以使用Docker镜像ID,其摘要信息是本地镜像配置文件的摘要。也可以使用manifest的摘要,这是另外一个唯一的标识符。比如说我们在使用Docker push命令的时候,会发现它的标准输出里面最后一行会输出一个摘要字符串,这个字符串就是manifest摘要。这两个摘要信息是不一样的。但是有依赖关系,比如manifest文件里面其实就保存了那个镜像ID,所以在给定一个manifest文件的基础上只可能有一个镜像ID是与之对应,但是反过来就不一定了。因为manifest还有一些别的信息。

上图里面有两个镜像中心,即两个registry,多个节点上都有Docker。在高版本的Docker基础上,从镜像中心拉镜像A到上面这个Docker,然后查看它的镜像ID。另外一个Docker也从相同registry拉镜像ID,然后查看镜像ID,它能保证这两个镜像ID是一样的。如果把这个镜像推到别的仓库,换一个名字,用Docker tag重新打一个标签,又把这个镜像推到了另外一个镜像中心,然后又有第三个Docker的节点把它拉下来,这些操作都能保证不管这个镜像怎么传输,其镜像ID是一致的,即内容可定位的。

唯一识别某个镜像:通过镜像版本来管理镜像,好处是镜像版本带有语义信息,缺点是镜像版本可以被覆盖;通过manifest摘要来管理镜像,好处是镜像唯一确定,缺点是镜像版本不带有语义信息。

正确管理容器内的进程

镜像要求指定容器的首进程,即完成三个工作:给这个容器里面其他进程正确传递信号,正确回收僵尸进程,等待子进程的退出。

编译型语言和解释型语言

对编译性语言和解释性语言,其构建是有区别的。编译性语言比如说JAVA,它本身是有源代码,需要经过一个编译打包的过程,生成一个war包,最后再去执行构建,这是比较推荐的方式。所以,建议对于编译性的语言,首先对它做一个打包动作,打包生成的war包放到Dockerfile上下文目录,然后通过拷贝的方式添加到镜像中,而不是在Dockerfile远程拉下来。这里推荐使用阿里云的持续构建平台——CRP平台。这个平台做的事情就是,拿到源代码之后,首先打包,打成war包作为一个Dockerfile构建上下文的一个输入,然后再拿到镜像中心构建服务进行构建。

但是像PHP这种不需要编译的解释性语言来说,可以考虑直接进行构建。

时间: 2024-10-03 00:31:27

Docker镜像原理和最佳实践的相关文章

【转载】Docker 镜像优化与最佳实践

阿里云高级研发工程师御坂在云栖TechDay41期的线下沙龙活动中分享了Docker镜像优化与最佳实践.本文为沙龙内容回顾. 从Docker镜像存储的原理开始,针对镜像的存储.网络传输,介绍如何在构建中对这些关键点进行优化.并介绍Docker最新的多阶段构建的功能,以解决构建依赖的中间产物问题. 镜像概念 镜像是什么? 从一个比较具体的角度去看,镜像就是一个多层存储的文件,相较于普通的ISO系统镜像来说,分层存储会带来两个优点: 一个是分层存储的镜像比较容易扩展,比如我们可以基于一个Ubuntu

Docker 镜像优化与最佳实践

云栖TechDay41期,阿里云高级研发工程师御坂带来Docker镜像优化与最佳实践.从Docker镜像存储的原理开始,针对镜像的存储.网络传输,介绍如何在构建中对这些关键点进行优化.并介绍Docker最新的多阶段构建的功能,以解决构建依赖的中间产物问题.   以下是精彩内容整理: 镜像概念 镜像是什么?从一个比较具体的角度去看,镜像就是一个多层存储的文件,相较于普通的ISO系统镜像来说,分层存储会带来两个优点,一个是分层存储的镜像比较容易扩展,比如我们可以基于一个Ubuntu镜像去构建我们的N

《大数据系统构建:可扩展实时数据系统构建原理与最佳实践》一1.9 示例应用:SuperWebAnalytics.com

本节书摘来自华章出版社<大数据系统构建:可扩展实时数据系统构建原理与最佳实践>一书中的第1章,第1.9节,南森·马茨(Nathan Marz) [美] 詹姆斯·沃伦(JamesWarren) 著 马延辉 向 磊 魏东琦 译,更多章节内容可以访问"华章计算机"公众号查看. 1.9 示例应用:SuperWebAnalytics.com 在本书中,我们将创建一个大数据应用程序示例来说明一些概念.我们将为Google Analytics构建数据管理层-比如服务.该服务将能够每天追踪

深入分析Docker镜像原理 (转载)

深入分析Docker镜像原理 (转载) 发表于2015-08-21 13:50| 24023次阅读| 来源CSDN| 6 条评论| 作者孙宏亮 云计算DockerDaoCloud 摘要:8月20日晚上8点30分,CSDN Container微信群邀请到DaoCloud软件工程师孙宏亮,他带来了Docker镜像原理的深度分享,分享内容包含两个部分:1.Docker镜像的基本知识:2.Dockerfile.Docker镜像与Docker容器的关系. 分享简介:Dockerfile重塑新镜像,定义的不

大数据系统构建:可扩展实时数据系统构建原理与最佳实践》一3.2 Apache Thrift

本节书摘来自华章出版社<大数据系统构建:可扩展实时数据系统构建原理与最佳实践>一书中的第3章,第3.2节,南森·马茨(Nathan Marz) [美] 詹姆斯·沃伦(JamesWarren) 著 马延辉 向 磊 魏东琦 译,更多章节内容可以访问"华章计算机"公众号查看. 3.2 Apache Thrift Apache Thrift(http://thrift.apache.org/)是一个可以用来定义静态类型化的.可实施模式的工具.它提供了接口定义语言,以通用数据类型的术

OSGi原理与最佳实践(精选版)中第二个例子 找不到org.mortbay.jetty 这个Bundle 求解决办法??

问题描述 OSGi原理与最佳实践(精选版)中第二个例子找不到org.mortbay.jetty这个Bundle求解决办法?? 解决方案 解决方案二:看下下面帖子配置http://blog.sina.com.cn/s/blog_9671d5180101r5dg.html

镜像命名的最佳实践 - 每天5分钟玩转 Docker 容器技术(18)

我们已经学会构建自己的镜像了.接下来的问题是如何在多个 Docker Host 上使用镜像. 这里有几种可用的方法: 用相同的 Dockerfile 在其他 host 构建镜像. 将镜像上传到公共 Registry(比如 Docker Hub),Host 直接下载使用. 搭建私有的 Registry 供本地 Host 使用. 第一种方法没什么特别的,前面已经讨论很多了.我们将讨论如何使用公共和私有 Registry 分发镜像. 为镜像命名 无论采用何种方式保存和分发镜像,首先都得给镜像命名. 当

学习笔记TF061:分布式TensorFlow,分布式原理、最佳实践

分布式TensorFlow由高性能gRPC库底层技术支持.Martin Abadi.Ashish Agarwal.Paul Barham论文<TensorFlow:Large-Scale Machine Learning on Heterogeneous Distributed Systems>. 分布式原理.分布式集群 由多个服务器进程.客户端进程组成.部署方式,单机多卡.分布式(多机多卡).多机多卡TensorFlow分布式. 单机多卡,单台服务器多块GPU.训练过程:在单机单GPU训练,

深入分析 Docker 镜像原理

第一部分:Docker镜像的基本知识 1.1 什么是Docker镜像 从整体的角度来讲,一个完整的Docker镜像可以支撑一个Docker容器的运行,在 Docker容器运行过程中主要提供文件系统视角.例如一个ubuntu:14.04的镜像,提供了一个基本的ubuntu:14.04的发行版,当然此 镜像是不包含操作系统Linux内核的. 说到此,可能就需要注意一下,linux内核和ubuntu:14.04Docker镜像的区别了.传统虚拟机安装ubuntu:14.04会包含两部分,第一,某一个L