随着云原生、容器化、微服务、k8s等技术的发展,容器Docker也火了一把,同时也逐渐被软件开发者在实践中进行运用。个人在目前接手的项目、参与的项目或技术交流中,发现Docker已经非常普及。
对于大多数开发者来说,Docker之所以被广泛使用,最主要的原因可能就是方便,它提供了一套标准化的解决方案,极大地提升了部署、发布、运维的效率。因此,如果你的项目中目前还没有使用Docker,或者想深入了解一下Docker,这篇文章值得你一读。
在聊Docker是什么之前,我们先来回顾一下传统的产品开发上线涉及到的难点。一款产品从开发到上线,经历了开发环境、测试环境、生产环境等不同的操作系统、运行环境和应用配置等环境。在项目管理中,还涉及到不同版本以及不同版本之间兼容性等问题。
这些问题对开发人员和运维人员都是极大的考验,同时对各方的协作也有一定的要求。不然就会出现”代码在我这里运行的好好的啊“,这种尴尬的局面。而Docker的出现就是提供了一套用来解决此类问题的标准解决方案。
Docker的口号是”一次创建或配置,可以在任意地方正常运行“。如口号所说,Docker的出现对于开发和运维人员是一大福音,基于Docker可以方便地搞定标准化的发布流程,再也不用纠结不同环境导致的问题了。
其实,Docker的使用可以理解为:软件是带环境安装的,也就是说,安装的时候把原始环境一模一样的复制过来一份。这样也就消除了不同机器运行结果不同的问题。
那么,Docker是什么呢?Docker是一个开源的应用容器引擎,基于Go语言,并遵从Apache2.0协议开源。它可以让开发者打包应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。Docker可用于开发应用、交付应用、运行应用等场景。
容器是完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。Docker允许用户将基础设施中的应用单独分割出来,形成更小的部分容器,从而提高软件交付速度。
Docker从17.03版本之后分为CE(Community Edition: 社区版)和EE(Enterprise Edition: 企业版),通常使用社区版就可以满足大多数业务场景。
Docker容器与虚拟机很相似,但它们之间又有着很大的区别。
虚拟机是通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。创建虚拟机时,会将实体机的部分硬盘和内存容量作为虚拟机的硬盘和内存,每个虚拟机都有独立的硬盘和操作系统,可以像使用实体机一样对虚拟机进行操作。
虚拟机会消耗大量系统资源和开销,尤其是当多个虚拟机在同一物理服务器上运行时,每个虚拟机都有自己的子操作系统,大量精力以及资源被用于虚拟化的部署和运行上。
容器类似于虚拟机,只是容器不是完整的操作系统,容器通常只包含必要的操作系统包和应用程序,这就是它们轻量级的原因。
可以出,传统的虚拟机是在宿主机之上,又添加了一个新的操作系统,这就导致了虚拟机的臃肿,不适合迁移。而Docker是直接寄存在宿主机上,完全就会避免大部分虚拟机带来的困扰。
Docker是一个黑盒的进程,区别于传统的进程,Docker可以独立出一个自己的空间,不会使得在Docker中的行为以及变量溢出到宿主机上。
容器与虚拟机的各项区别:
那么,当在开发中使用了Docker能为我们带来哪些便利呢?先来看一张图。
在没有使用Docker时,我们开发完毕一个项目,需要打成war包或jar包。然后,在服务器上进行各种环境的安装、配置以及应用程序维护,比如:JDK、Tomcat、数据库等。
而且,上述的配置在开发环境、测试服务器、生产服务器(通常会有很多个),都需要进行一遍同样的操作,工作量相当繁重。在使用了Docker之后,我们可以自己创建一个空的镜像从头构建,也可以使用公共仓库中已经构建好的镜像,直接使用。当需要在不同环境中进行部署时,直接使用构建好的镜像即可,一次构建,多环境多次使用,方便快捷。
对比传统的运维发布方式,Docker有以下6大优势:
1、更高效地利用系统资源
Docker对系统资源的利用率更高。因为容器不用硬件虚拟以及运行完整操作系统等额外开销,无论是应用执行速度、内存损耗或者文件的存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,相同配置的主机,往往可以运行更多数量的应用。
2、更快的启动时间
传统的虚拟机技术启动应用服务往往是分钟级别的,而Docker由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间,大大的节约了开发、测试、部署的时间。
3、一致的运行环境开发中常见的问题是环境一致性问题,由于开发测试生产环境的不一致,导致有些bug没能在开发过程中被发现,而Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现“代码在我机器上能跑,这不怪我啊”这类问题。
4、持续交付和部署对开发和运维(DevOps)来说,最希望的就是一次创建或配置,可以在任意地方正常运行,使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署。
5、更轻松迁移Docker确保了执行环境的一致性,使得应用的迁移更加容易,Docker可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户不用担心运行环境的变化导致应用无法正常运行的情况。
6、更轻松的维护和拓展
Docker使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得十分简单。此外,Docker团队同各个开源项目团队一起维护了一大批高质量的官网镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
在使用Docker时,我们要掌握Docker中的一些核心组件及概念。
来看一张Docker的架构图:
Docker的基本组成是由镜像(image)、容器(container)、仓库(repository)构成。
Docker镜像就是一个只读的模板,是文件与meta data的集合。镜像是基于分层的实现的,每一层都可以添加删除文件,从而形成新的镜像。
镜像可以理解为是一个树状结构,每一个镜像都会依赖于另一个镜像,这个依赖关系体现在Docker镜像制作的Dockerfile中的FROM指令上的。
镜像可以用来创建Docker容器,一个镜像可以创建多个容器。
Docker利用容器独立运行的一个或一组应用。容器是用镜像创建的运行实例,是在image的最后一层上面再添加一层。容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
容器与镜像相对比:镜像负责存储和分发,容器负责运行,它们之间的关系可以类比Java中类和实例的关系。
容器可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的Linux环境和运行在其中的应用程序。
仓库是集中存放镜像文件的场所,它有点类似于Maven/Git的仓库,当我们需要镜像文件时,可以从远程仓库中拉取。
仓库和仓库注册服务器(Registry)是有区别的。仓库注册服务器上存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。目前最大的公开仓库是Docker Hub。