目录
前言
先赞后看,月入百万
我的公众号「Rui的后端手册」
物理机部署
拿一个经典的 java web程序来说:
- 在服务器上安装jdk环境和tomcat服务器
- 使用scp或 ftp将打包好的程序上传的服务器。
- 运行Jar包,或者将War包放到Tomcat的对应目录
物理机部署的问题
- 多个程序之间缺乏有效的隔离,例如某个程序占满cpu,其他程序一起GG
- 迁移,维护困难
- 扩容部署困难
- 安全性问题,一个程序被入侵,物理机整个沦陷
虚拟机部署
大名鼎鼎的VMware
- 在虚拟机里安装系统首先需指定相关的硬件配置,比如:cpu核数、内存等
- 然后找一个系统镜像ISO文件
- 其他的和在物理机上装系统类似
虚拟机原理和缺点
在操作系统之上,虚拟硬件,提供镜像运行的必须硬件环境。之后操作系统镜像就可以 像运行在真实的硬件之上一样启动,提供服务
从这里看到,虚拟机是真正的操作系统,可以提供完整的隔离性和安全性。但在程序部署上面仍不方便
容器化部署
代表技术:Docker
让程序部署变得简单,则是docker这个容器技术起飞的关键。
docker其实是提供了一种非常便利的打包机制。这种机制直接打包了运行某个软件所需的所有内容,包括代码、运行时所需的库、环境变量和配置文件,从而保证了本地环境和云端环境的高度一致
Docker核心概念
镜像:
一个镜像代表一个应用及其环境,他是一个只读的文件,如 mysql镜像,tomcat镜像,nginx镜像等容器:
镜像每次运行之后就是产生一个容器,就是正在运行的镜像,特点就是可读可写仓库:
用来存放镜像的位置,类似于maven仓库,也是镜像下载和上传的位置dockerFile:
docker生成镜像的配置文件,可以自定义dockerFile并用docker build
指令生成自定义镜像tar:
一个对镜像打包的文件,日后可以还原成镜像
Docker架构
docker client
:用户操作的终端,向docker daemon
发送指令
docker daemon
:守护进程,用来处理指令。比如:
docker pull <镜像名+版本号>
从远程仓库registry
拉取镜像docker run <镜像名+版本号>
运行镜像,生成容器docker build
根据dockerFile
生成自定义镜像
Docker底层原理
容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用“装”起来的技术。
这样,应用与应用因为有了边界而不至于相互干扰,而被装进集装箱的应用,也可以被方便地搬来搬去。
Namespace 机制
docker容器中的进程看不到容器外部的进程,一般容器中只有一个进程,就是我们的应用,这个进程看到的自己的pid=1,而在宿主机中又是另一个pid
底层调用了Linux的Namespace机制,不同NameSpace的进程看不到彼此,有着独立的进程视图
Cgroups机制
Linux 内核用来为进程设置资源限制的机制,全称是 Linux Control Group
主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽
Docker image
docker的镜像实际是由一层一层的文件系统组成。
UnionFS(联合文件系统):
- Union文件系统是一种分层的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加。
- Union文件系统是Docker镜像的基础。这种文件系统特性:就是一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
镜像是包含多层,可划分为:
- 只读层
- Init层
- 可读写层
当在可读写层删除一个文件,就会创建一个.wh.filename文件,将下层文件遮住,这样进程就看不到了,也不会修改下面的只读层。
这样的文件系统,有利于复用
用一个镜像启动多个容器,他们就可以复用只读层,不用再单独copy一份。
但是如果要修改只读层的文件会怎么样呢?
所有的增删查改操作都只会作用在读写层(容器层),相同的文件上层会覆盖掉下层
比如修改一个文件的时候,首先会从上到下查找有没有这个文件,找到,就复制到容器层中修改,修改的结果就会隐藏掉下层的同名文件,这种方式也被称为copy-on-write。
容器是一个“单进程”模型。
容器的“单进程模型”,是指容器没有管理多个进程的能力。
容器里 PID=1 的进程是我们要跑的应用,而容器会和PID=1的进程绑定
可以通俗理解为:容器=主进程
我们可以用docker exec
进入容器内部,并创建其他进程,但其它进程只是主进程创建的子进程。
而这些子进程出现异常,容器是不管的。那么这些子进程异常退出时,你该怎么知道呢?进程退出后的垃圾收集工作,又该由谁去做?
因此,容器里是可以运行多个进程的,但应该只运行一个进程
Docker的简单理解
Docker最核心的原理实际上就是为待创建的应用进程:
- 启用 Linux Namespace 配置
- 设置指定的 Cgroups 参数
- 切换进程的根目录(Change Root)
重新认识Docker:
- 镜像就是操作系统的所有文件,加上我们自己的代码和相关环境
- 容器就是设置了Namespace和Cgroups的应用进程
- 这个进程看到的文件系统是镜像中的文件系统
- 能看到的资源视图(网络、挂载点、进程等)受Namespace影响
- 能使用的硬件资源受Cgroups影响
Docker构建小技巧
- Dockerfile文件每一个命令都会生成一层不变的层会被缓存下来,最好让变化的层在最后,这样docker就可以利用缓存了
- Docker架构是C/S架构,docker build会将Dockerfile所在目录上下文打包发到docker守护程序上,通过创建.dockerignore文件,排除所有不用的文件,可以加快速度