Docker,一个在程序员界鼎鼎大名的软件,部署项目离不开docker,就像西方离不开耶路撒冷,今天来讲讲docker是怎么闯进程序员的生活里,并且成为了一个可靠的好大哥的。
docker从何而来
阶段一:程序员小骇最开始的时候,写的都是一些小型项目,例如一个经典的图书馆管理系统,只需要在linux上安装个jdk环境,甚至只需要jre,把jar包扔到服务器上,java -jar就好了。
阶段二:随着服务越发复杂,小骇找到了一个开源的图书管书籍推荐项目。由于资金窘迫,小骇只有一个主机可供部署项目。但是这个开源项目需要的jre是17,而前一个项目是idk8。
这里就出现了一个核心问题,当一个主机的环境,无法满足多个项目的环境配置需求。
不只是语言的环境,其他软件比如mysql5.7,或是mysql8.0都会带来环境冲突问题。
如何处理这种问题呢?小骇想到了,那不如在我的主机里安装jre8和jre17两个版本吧。 安装上之后,小骇发现了一个新的问题。
你在一个linux上安装了两个环境,突然发现,启动的时候就需要分别指定。
# 项目A用 jre8
/usr/lib/jvm/jre8/bin/java -jar a.jar
# 项目B用 jre11
/usr/lib/jvm/jre11/bin/java -jar b.jar
之后所有类似的内容,都要找到对应的路径和版本。会形成硬编码,众所周知硬编码的危害。当你需要换环境或者升级版本的时候,硬编码就会突然给你蹦个bug出来。而当你一处需要硬编的时候,那么要你硬编码的地方肯定不止一处。
而且,作为环境变量,其拥有特别的默认含义。如果你多了一些环境,那么这个主机中,我想做一些相关操作的时候,我还得审视一遍环境变量是哪个。在java环境之上的一些软件,则不知道其依赖的到底是哪个环境,发散出更多的问题。
所以,我们能看到,多项目部署,带来的是环境紊乱问题。
怎么才能处理好这样的问题呢?
渐渐地,有大佬提出了一个猜想,能不能运用生活中的集装箱思维,来承载这个项目与环境的问题。
所谓集装箱,就是海运的时候,货物不是直接摆在货船上的,有的货物是小的,有的货物是大的,有的是液体,有的是固体,形状各不相同,无法规矩地排列在一块儿。
然而,当我们用制式的集装箱来装载货物,由于集装箱的外形是均衡贴合的,所以可以有效地摆在一个船上。
将集装箱思想运用到环境中,能不能用一个集装箱,来装载要部署的项目呢,而项目所需要的环境,单独处在集装箱中,而非船身来适应一种货物。
于是,真的出现了这样思维的软件,Docker!!!
所谓docker,就是能在一台机器上开辟许多个独立环境,就像一个个集装箱,它们之间互不干扰,各自有各自的配置。例如,我完全可以在容器1使用jdk8而容器2使用jdk17,它们之间随意设定不会矛盾,因为是不同的集装箱,各自是独立的空间。
docker的环境,既不相互影响,也不影响船身(主机)。而是把 环境+软件打包到一个容器之中,环境跟着项目走。
甚至于,除了项目,你还可以在主机上装载多个mysql版本,也用docker放入就好啦。
如何做到的
如果要深入一点docker的实现,它利用了linux内核的两个功能。
其一,命名空间namespace,用来实现,“看不见,摸不着”的隔离,每个namespace拥有自己的独立进程ID和文件系统。
其二,控制组cgroups用来实现不能去抢走其他人cpu,内存的限制,也就是资源隔离。