在工作中,我们掌握了微服务的服务注册与发现(nacos)、配置中心(nacos)、远程服务调用(feign)、网关(gateway),同时借助Idea编译工具多次完成本地服务启动、部署和验证。但是我们假想下面场景:

  • 开发人员A写好的代码-->开发人员小王的电脑上运行,小周必须保证跟小王一样的系统环境(JDK/MySQL等)
  • 系统代码部署从DEV-->TEST-->PRE-->PROD,每个环节都必须保证一样的系统环境(同上)
  • 分布式系统中依赖组件非常多,组件与组件之间的部署往往会产生一些冲突(端口/依赖/环境等)

保证版本一致会耗费我们大量的时间和精力,同时万一有问题产生,我们也很难第一时间考虑到是因为版本不一致导致的问题。因此我们需要一套可以平滑切换的部署引擎,这就是本节我们学习的Docker

1.什么是Docker

Docker 是一个开源的容器化平台,用于打包、分发和运行应用程序。它基于 Linux 容器(LXC)技术,并提供了简单且易用的工具和接口,使得开发人员可以轻松地创建和管理容器。

在 Docker 中,应用程序及其所有依赖项被组织为一个独立的容器。容器是基于镜像创建的运行实例,它具有独立的文件系统、进程空间和网络接口。每个容器都可以在任何支持 Docker 的环境中运行,包括开发机、测试环境和生产服务器。可以解决一下问题:

  • 解决依赖兼容问题
  • 解决操作系统差异问题

1.1. 解决依赖兼容问题

思考:Docker是如何解决依赖兼容问题?

主要通过一下两种方式解决:

  • 将应用的Libs(函数库),Deps(依赖)、配置和应用打包在一起
  • 将每一个应用运行在相互隔离的容器中运行,避免相互干扰。 打包方式如下图:
  • 深入理解 Docker:探索容器技术的核心概念_函数库

  • 使用上面方式进行打包好的应用(java应用程序就不再是原来的jar包),里面不仅包含了应用本身,还包含了应用所需要的Libs、Deps,这样就不再需要在操作系统上安装Libs和Deps,那么自然就不存在应用兼容问题

思考:上面说的解决了应用的冲突问题,但是我们的开发、测试和正式环境还是会存在差异(也就是操作系统可能会存在差异,那么我们如何解决)?

1.2. 解决操作系统环境差异

要解决这个问题,我们就需要先了解操作系统结构,结构如下:

  • 硬件: CPU、内存、磁盘等
  • 操作系统内核: 所有的Linux发行版内核都是Linux,但是发行版是基于Linux内核版进行扩展的,由各个Linux厂商开发、维护,例如有CentOS、Ubuntu、Fedora等,Linux内核的作用可以理解为是和计算机硬件进行交互
  • 系统应用: 操作系统自身提供的应用和函数库。这些函数库是对内核指令的封装(不同版本的操作系统函数库不太一样),方便开发人员使用。
  • 应用程序: 就是我们开发好的那些程序,例如:电商应用、Mysql、Nginx等等

linux从入门到精通介绍过,忘记的小伙伴可以自行查看一下。

深入理解 Docker:探索容器技术的核心概念_Docker_02

通过上面操作系统的介绍,我们已经知道Ubuntu和CentOS都是基于Linux内核,但是系统应用不同,提供的函数库有差异,如果将Mysql(Ubuntu版本)应用安装到CentOS上,那么他要调用的是Ubuntu函数库时,就会报错,原因就是匹配不到对应的函数库。

思考:Docker如何解决不同操作系统环境问题?


Docker解决不同系统环境的问题

  • 1.Docker将用户程序与所需要调用的系统(比如Ubuntu)函数库一起打包
  • 2.Docker运行到不同操作系统时,直接基于打包的库函数,借助于操作系统的Linux内核来运行

深入理解 Docker:探索容器技术的核心概念_文件系统_03

细心的小伙伴可能已经发现了,Docker和虚拟机很相似,那么Docker和虚拟机有什么区别?

2. Docker和虚拟机区别

想要了解两者之间的区别,我们还需要看一下他们的具体定义:

  • 虚拟机(Virtual Machine):是可以在一台电脑上通过软件的方式模拟出来若干台计算机,可以实现一台电脑“同时”运行几个操作系统,相互独立进行工作。同时,这几个操作系统之间还可以进行互联,形成一个虚拟网络。比如:可以在Windows系统上运行CentOS系统/
  • Docker:  是一个开源的应用容器引擎,他仅仅封装Libs(函数库),没有模拟完整的操作系统,共享同一个底层硬件设备。 相较于传统虚拟机而言,二者主要区别如下:

特性

Docker

虚拟机

性能

接近原生

性能较差

硬盘占用

一般为 MB

一般为GB

启动

秒级

分钟级

3. Docker架构

3.1. Docker核心概念

镜像

  • 镜像(Image):镜像是一个只读模板,包含了运行应用程序所需的所有文件系统、依赖库、应用程序代码等内容。除此之外镜像还包含配置参数(环境变量、用户等),但是不包含任何的动态数据,镜像构建后不会改变,可以类比为Java中的类

Docker 镜像采用分层构建的方式来实现高效的镜像管理和存储。镜像分层构建通过将一个完整的镜像拆分为多个只读的文件系统层(Layer),每个层都包含了特定的文件和目录变更。

以下是镜像分层构建的主要原理和优势:

  • 原理每个镜像层都是一个只读的文件系统,可以包含文件、目录、依赖库、运行时环境等。 每个层都包含了与前一层的差异,这种差异是通过文件系统的快照和增量存储来实现的。 当多个镜像共享相同的层时,这些层可以在磁盘上进行共享,节省存储空间每个层都包含了与前一层的差异,这种差异是通过文件系统的快照和增量存储来实现的。 容器在运行时会在所有层之上创建一个可写层,用于保存容器运行时的变更和数据。
  • 优势
  • 高效的存储管理:由于层的共享,镜像只需要存储不同的层和差异,更加节省存储空间。
  • 快速的镜像构建和传输:当构建镜像时,只需构建变化的层,而不是完整的镜像,加速了构建过程。同时,镜像的传输也更快,因为只需要传输变化的层。
  • 灵活的镜像定制:通过添加、删除或修改特定层,可以定制和修改现有的镜像,而不必重新构建整个镜像。
  • 更好的缓存和复用:Docker 引擎可以缓存每个层,并在构建时进行重复使用。当多个镜像共享相同的层时,这些层可以被多次复用,从而提高了构建和部署的效率。 通过镜像分层构建,Docker 提供了一种高效、可靠且可定制的方式来管理和交付应用程序。开发人员可以利用已有的层和镜像,减少构建时间和存储空间,同时也使得镜像的更新和维护更加方便。

容器(Container)

  • 容器(Container):容器是基于镜像创建的运行实例,它具有独立的文件系统、进程空间和网络接口。容器可以被快速启动、停止、删除和复制。

容器和镜像的联系和区别:

镜像,就是把一个应用在硬盘上的文件、及其运行环境、部分系统函数库文件一起打包形成的文件包。这个文件包是只读的。容器,就是将这些文件中编写的程序、函数加载到内存中允许,形成进程,只不过要隔离起来。因此一个镜像可以启动多次,形成多个容器进程

仓库(Registry)

仓库是用来存储和共享镜像的地方。

镜像构建完成后,可以很容易在当前宿主机运行,但是想要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry就是这样一个服务。 一个Docker Registry可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常一个仓库会包含一个软件的不同版本镜像,标签用于区分版本,如不给出标签,默认latest作为标签。 Docker Registry公开服务 开发给用户使用、允许用户管理镜像的Registry服务,可避免重复劳动,如Redis/Nginx等

  • 官方的Docker镜像的托管平台:Docker Hub。
  • 国内代理的DcokerHub公开服务:网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库 等。

深入理解 Docker:探索容器技术的核心概念_文件系统_04

Docker Registry私有服务

公司内部使用、迭代的镜像Registry服务,需要用户自己完成代码打包、镜像上传。

总结:

通过本文的介绍,相信小伙伴已经对Docker有了更深入的了解,并且意识到它在现代软件开发和部署中的重要性和广泛应用。作为一种轻量级的容器化平台,Docker可以帮助开发人员简化环境配置、提高部署效率和资源利用率,并促进团队协作和持续交付。在未来的软件开发过程中,不妨尝试使用Docker来优化您的工作流程,提升开发体验和项目质量。