一、物理部署的痛点:
- 部署慢
- 需要物理机
- 部署物理机操作系统(CentOS, RedHat)
- 成本高(部署一个集群,需要购买多台服务器)
- 资源浪费(如果机器规格很好,8核32G,就单跑个Nginx)
- 难迁移和扩展(一台机器故障,或者需要迁移新的机器,需要把整个部署的步骤全部从新来一遍)
- 被限定硬件/操作系统等(如果两个机器硬件/系统等不相同,扩展和迁移可能会存在兼容性问题))
二、虚拟化技术
- 一台物理机可以通过VMware安装多个操作系统
- 每个操作系统可以运行单独的app
KVM-QEMU
目标:虚拟出一台完整的机器,包括硬件(vCPU,vMEM),软件操作系统(windows,linux)
KVM全称for Kernel-based Virtual Machine,意为基于内核的虚拟机。
在虚拟化底层技术上,KVM和VMware后续版本一样,都是基于硬件辅助虚拟化实现。
不同的是VMware作为独立的第三方软件可以安装在Linux、Windows、MacOS等多种不同的操作系统之上,而KVM作为一项虚拟化技术已经集成到Linux内核之中,可以认为Linux内核本身就是一个HyperVisor,这也是KVM名字的含义,因此该技术只能在Linux服务器上使用。
三、容器技术-LXC
虚拟出一台计算机的成本高还是只虚拟出一个隔离的程序运行环境的成本高?答案很明显是前者。一台物理机可能同时虚拟出10台虚拟机就已经开始感到乏力了,但同时虚拟出100个虚拟的执行环境却还是能够从容应对,这对于资源的充分利用可是有巨大的好处。
不同于虚拟化技术要完整虚拟化一台计算机,容器技术更像是操作系统层面的虚拟化,它只需要虚拟出一个操作系统环境。
四、Docker
对进程进行封装隔离,属于操作系统层面的虚拟化技术。使用宿主主机的内核(linux内核),自由替换内核上层的发型版本(CentOS,Ubuntu)。
尽可能的保持 开发,测试,生产 环境一致性。
1、docker 引擎
2、组成
-
镜像 images (镜像,构建容器)
-
容器 containers (应用程序跑在容器中,运行实例)
-
网络 network
-
数据卷 data Volumes
-
仓库 registry
3、安装
4、常用命令
#启动/重启/停止docker
docker start | restart | stop
#拉取镜像,不写版本号就是最新版本
docker pull mysql:5.7.31
#查看镜像
docker image ls
#查看运行容器
docker ps
#查看所有的容器
docker ps -a
#停止容器 容器id/容器name
docker stop id/name
#运行镜像,生成容器
# -d 后台运行
# -p 端口映射 宿主主机端口:容器内端口 (大写P则是随机端口)
# -e 配置环境
# --name 容器名字
# mysql 镜像名字
docker run -d -p 16379:6379 --name mysql-5.7.31 mysql
# -i 交互式命令操作
# -t 开启一个终端
# bash 进入容器后,执行的命令
docker run -it -p xx:xx id bash
# 进入一个容器
docker exec -it xxxx /bin/bash
# 查询容器的信息
docker inspect 容器id
# 构建docker 镜像
# -f dockerfile文件的位置
# -t 容器名,注意后面有个 .
docker build -f dockerfile -t 容器名 .
#看到镜像的构建过程
docker history 容器id
# 发布镜像
docker push
5、生命周期
6、Docker 镜像原理
UnionFS (联合文件系统)
联合文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(将多个目录合并成一个虚拟文件系统)。联合文件系统是镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性: 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker 镜像加载原理
-
bootfs (boot file systen) linux 启动就会加载bootfs文件系统,在Docker镜像的最底层就是bootfs,与典型的Linux/Unix系统一样,包含加载器和内核。当boot加载完成之后整个内核就在内存中,此时内存的使用权已经由bootfs转交给内核,此时系统也会卸载bootfs。
-
rootfs (root file systen) 在bootfs 之上,比较Linux,就等于是各大操作系统的发行版(CentOS, Ubuntu)
分层理解
7、Commit 镜像
#docker commit 提交容器成为一个新的副本
docker commit -m="提交信息描述" -a="作者Agao" 容器id
8、容器数据卷(双向绑定)
如果数据都在容器中,如果删除了容器,那么数据就会被删除。如果做持久化?例如 数据库数据,如何存储在本地,将容器和宿主主机做数据的同步。
命令挂载 -v
# 如果不指定主机目录
# 默认是:/var/lib/docker/volumes/xxxxxxx(贼长一串字母)
# -v 容器内目录 匿名挂载
# -v 卷名:容器内目录 具名挂载
# -v 主机目录:容器目录 指定目录挂载
docker run -it -v 主机目录:容器目录 centOS /bin/bath
拓展:增加权限
# ro readonly 只读 该路径只能通过宿主主机操作,容器内不能操作
# rw readwrite 可读可写
docker run -d -P --name MyNginx -v myNginx:/etc/nginx:ro nginx
docker run -d -P --name MyNginx -v myNginx:/etc/nginx:rw nginx
拓展:父子挂载
# --volumes-from 父级容器
docker run -it --name nginx2 --volumes-from nginx1 nginx
9、DockerFile
用来构建docker 镜像的文件,等于命令脚本。
- 关键字(指令)必须是大写
- #表示注释
- 每一个指令都会创建提交一个镜像层,并提交。
命令:
# 最基础的镜像(这个镜像的妈妈是谁)
FROM centos
# 镜像的作者(谁负责养它)
MAINTAINER agao<agaozijing@qq.com>
# 镜像构建的时候需要运行的命令(你想让他干些啥)
RUN yum -y install vim
# 步骤,添加tomcat镜像压缩包,会自动解压(给它点创业资金)
ADD apache-tomcat-9.0.22.tar.gz /user/local
# 构建的时候设置环境变量
ENV MYPATH /user/local
# 镜像工作的目录,进入容器直接到这个目录(在哪儿干活儿)
WORKDIR $MYPATH
# 挂载目录(行李放在哪儿)
VOLUME ["volume1","volume2"]
# 指定对外暴露的端口(给他开个门儿)
EXPOSE 80
# 指定容器启动时候需要运行的命令,只有最后一个会生效,会被覆盖
CMD /bin/bash
# 指定容器启动时候需要运行的命令,追加式的命令
ENTRYPOINT
# 当一个被继承dockerfile这个时候就会运行,触发指令
ONBUILD
# 类似ADD,拷贝文件到镜像中
COPY
eg:
10、发布镜像
DockerHub
- 地址:hub.docker.com 注册账号
- 登录账号
#登录dockerHub账号
docker login -u 账号
- 发布镜像
# 容器名字:tag 版本号
docker push 容器:2.0
11、Docker 网络
容器之间的通信(evth-pair)
evth-pair: 就是一对虚拟的设备接口,他们都是成对出现的,充当一个桥梁,连接各种虚拟网络设备。
例如:ES 和 Kabana
安装docker,会生成一个docker0 的网卡,通过桥接模式连接到宿主主机。 容器启动,docker会自动给容器分配网卡,生成的网卡信息,会同步到宿主主机上。 宿主主机是能直接ping通容器的ip。
# 查所有的网卡地址
ip addr
网络通信模型
Docker0 就充当了一个路由器的作用,docker中的所有容器(除指定了--net的容器)都是连接到这个路由器的设备。 其ip都是由docker0成对分配给他们。
容器互联 --link
容器每次重启,docker0分配给他的ip 会改变,这样就会导致每次都需要重写ip 例如 springboot 服务,里面连接的mysql地址,每次重启mysql之后,都需要修改springboot的配置文件。 容器互联就可以解决这个问题,可以通过容器name的方式,使得容器之间互联:
docker run -d -P --name mySpringBoot --link mySQL
# 绑定之后,可以直接通过A的名字ping通B的名字,反之不可,因为B未配置跟A的绑定关系
docker exec -it ping mySQL
实质: 在mySpringBoot 容器中,/etc/hosts 文件中配置了mySQL的映射关系 ip mysql 容器id
自定义docker网络
#查看所有的docker网络
docker network ls
网络模式
- bridge: 桥接
- none: 不配置网络
- host: 和宿主主机共享网络
- container: 容器网络联通
创建network
# 需要配置 模式,子网,网关,网络名字
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 myNet
# 将容器放到自定义的网络中 --net myNet 指定
docker run -d -P --name myTomcat --net myNet tomcat
使用这种自定义网络,可以直接使用容器name 去ping,不用再做容器互联(--link)
连接容器到网络
docker network connect 网络名(myNet) 容器name(myTomcat)
12、微服务打包发布Docker
- 构建项目
- 打包应用(maven package)
- 编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8081"]
EXPOSE 8081
ENTRYPOINT["java","-jar","/app.jar"]
- 将jar和dockerfile 传到服务器
- 构建镜像
docker build -t springbootDemo
- 发布运行
docker run -d -p 8081:8081 --name myBootDemo springbootDemo