一、微服务出现的问题
微服务虽然具备很大的优势,但它的劣势一样很明显,服务的拆分通用给服务的部署带来了很大的麻烦。
- 分布式系统中,需要依赖的组件非常多,不同组件的部署往往会产生冲突,
产生兼容性的问题。
而且,在不同的服务器重复部署时,服务器的环境不一定一致,也会遇到各种问题。
开发、测试、生产环境有差异环境的不同,甚至相同的服务可能会部署到不同的系统环境中。
如相同的服务部署到了CentOS、Ubuntu、Fedora系统中。
-
例如下面的项目中,部署时需要依赖于node.js、Redis、RabbitMQ、MySQL等,
-
这些服务部署时所需要的函数库(Lib)、依赖项(depe)各不相同,甚至会有冲突。
-
甚至部署不同的操作环境中(CentOS、Ubuntu、Fedora)。
1,Docker解决依赖,函数兼容问题
不同的服务可能需要不同的依赖与函数库。如node.js、Redis、RabbitMQ、MySQL等。
为了解决这个问题,Docker将应用的Libs(函数库)、Deps(依赖)、配置与应用一起打包。
同时将每个服务放到一个隔离容器去运行,防止相互干扰。
- 如上图所示:
- 打包好的服务不仅包含组件本身,也包含组件需要的函数库与依赖。
- 每个组件相互之间又是隔离的,避免了干扰。
2,.Docker解决操作系统环境差异
在上面,Docker解决了不同组件的兼容问题。
但是,开发,测试,运行环境的差异如何改变。当操作环境不同时,相同的服务如何正常的运行。
2.1,了解操作系统结构
- 结构包含:计算机硬件,系统内核,系统应用
计算机硬件:CPU,内存,磁盘
系统内核:无论是CentOS、Ubuntu、Fedora,系统内核都是Linux。
系统应用:操作系统本身提供的函数库。
2.2,如何解决系统环境差异
由此可知,无论是什么系统应用,他们的内核都是一样的。
相同的应用在不同的系统之所以不兼容,是因为不同系统的函数库不一致。
如,将一个Ubuntu版本的MySQL应用安装到CentOS系统,MySQL在调用Ubuntu函数库时,会发现找不到或者不匹配,就会报错了。
Docker提供了解决的办法:
Docker将用户程序与所需要调用的系统(比如Ubuntu)函数库一起打包。
当需要对应的函数与系统内核交互时,直接使用本地(自己打包)的函数库,
不在需要系统应用本身提供的函数库了。
2.3,总结:
对于操作系统而言,是【部署的服务】调用【系统应用自身函数】,【系统应用】调用【系统内核】,
【系统内核】操作【计算机硬件】。
当【服务】部署到不同的系统环境时,因为【系统应用自身函数】不同,导致【服务】在访问【系统应用】
时会因为函数不同而失败。
所以Docker想了一个办法,不使用【系统应用自身函数】,将需要的【系统函数】与【服务】一起打包。
于是步骤变成了,【服务】通过访问【自身打包的函数(本地函数)】直接与【系统内核】交互,因为系统内核是一样的,就不存在系统环境差异的问题了。
说白了,Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可以在任意Linux操作系统上运行
3,Docker和虚拟机的区别
Docker可以让一个应用在任何操作系统中非常方便的运行。而以前我们接触的虚拟机,也能在一个操作系统中,运行另外一个操作系统,保护系统中的任何应用。
两者有什么差异呢?
虚拟机(virtual machine)是在操作系统中模拟硬件设备,然后运行另一个操作系统,比如在 Windows 系统里面运行 Ubuntu 系统,这样就可以运行任意的Ubuntu应用了。
Docker仅仅是封装函数库,并没有模拟完整的操作系统,如图:
对比来看:
小结:
Docker和虚拟机的差异:
-
docker是一个系统进程;虚拟机是在操作系统中的操作系统
-
docker体积小、启动速度快、性能好;虚拟机体积大、启动速度慢、性能一般
二、Docker结构
镜像(Image):Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。
容器(Container):镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器进程做隔离,对外不可见。
可以理解为,镜像就是一个类,而容器就是类创建的对象。
一个类可以创建多个对象,且各个对象之间没有关联。
Docker开启多个服务的原理:
以MySQL为例,如何使用Docker创建多个MySQL。
在Docker使用MySQL镜像创建两个MySQL。
两个MySQL的端口是一样了。
但是在Linux系统中两个MySQL对应的端口是不一样的。
因为只有宿主机才可以访问Docker,而我们可以访问宿主机。
如,第一个MySQL映射的端口是80
第一个MySQL映射的端口是81
三、Docker操作
docker run -d -p 81:8080 --name tomcat81 tomcat:8.5.13
【-d】
- 后台运行
【-p 81:8080】
端口,tomcat端口8080对应的Linux端口81
81端口是唯一的
【–name tomcat81 tomcat:8.5.13】
- 创建的tomcat名为tomcat81 ,唯一
- tomcat:8.5.13,表示要下载的tomcat版本
1,镜像指令
1.0,概述
镜像是一个文件
Docker将应用程序以及所需要的依赖库、函数库、环境、配置文件等文件打包在一起,
形成的文件就是镜像。
- 镜像由两部分组成:
- 镜像名称:镜像版本
- 如:【mysql:5.7.25】、【tomcat:8.5.13】
1.1,查看本地镜像
- docker images
1.2,搜索镜像
docker search 镜像名称
需要联网,搜索网上的镜像
1.3,拉取镜像
docker pull 镜像名称:版本号
1.4,导出镜像成为一个tar文件
docker save -o [保存的目标文件名称] [镜像名称:版本号]
- 例如:【docker save -o nginx.tar nginx:latest】
- 一般建议拉取的镜像保存的文件后缀为【.tar】
- 【-o】表示output
1.5,删除镜像
docker rmi 镜像ID或者镜像名称
- docker rmi nginx:latest
- 通过镜像名:镜像版本删除
- 删除前一定要将容器停止
- rmi:【remove image】
1.6,导入镜像
docker load -i 镜像文件
- 【-i】:input
- 镜像文件就是1.4导出的。
1.7,为镜像命名
如果导入的镜像没有名称,可以手动为其命名:
- 一个没有名称的镜像,被叫做虚悬镜像
- docker tag 镜像ID 镜像名称:镜像版本
- docker tag 605c77e624dd nginx:latest
1.8,案例
拉取redis:3.2.10镜像,并导出到本地,再删除redis镜像,再导入
- docker pull redis:3.2.10
- docker save -o redis:3.2.10.tar redis:3.2.10
- docker rmi redis:3.2.10
- docker load -i redis:3.2.10.tar
2,容器指令
2.1,运行容器
docker run -d -p 宿主机端口:容器端口 --name 容器名称 -v 宿主机目录:容器目录 --rm --restart=always 镜像ID或者镜像名称
docker run -d -p 80:80 --name nginx -v /opt/nginx/html:/usr/share/nginx/html -v /opt/nginx/nginx.conf:/etc/nginx/nginx.conf 镜像ID
- 注意:【–rm 跟 --restart 不能同时使用】
- 【-d】:表示后台运行
- 【-p】:端口映射
- 【–name】:指定容器的名称(唯一)
- 【-v】:数据卷映射
- 【–rm】:停止容器后删除容器(–rm 跟 --restart 不能同时使用)
- 【–restart=always】:重启容器的方式,always表示重启Docker的同时重启容器
2.2,查看容器
查看正在运行的容器:【docker ps】
查看所有的容器(包含停止的):【docker ps -a】
查看正在运行的容器的id:【docker ps -q】
查看所有容器的id:【docker ps -aq】
2.3,停止容器
停止容器:【docker stop 容器id&容器名】
停止所有的容器:【docker stop $(docker ps -aq)】
2.4,启动容器
启动容器:【docker start 容器id&容器名】
可以开启多个容器,使用空格分开:【docker start 容器id&r容器名 容器id&r容器名 …】
2.5,重启容器
- 重启容器:【docker restart 容器id&r容器名】
2.6,删除容器
删除容器前必须先停止容器
删除容器:【docker rm 62efeb9922d4】
删除所有容器:【docker rm $(docker ps -aq)】
2.7,进入与退出容器
进入容器:【docker exec -it 容器ID或容器名称 bash】
docker exec :进入容器内部,执行一个命令
-it : 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
bash:进入容器后执行的命令,bash是一个linux终端交互命令
退出容器:【exit】
2.8,查看docker日志
- 查看docker日志:【docker logs 容器ID或容器名称】
3,数据卷指令
3.1,概述
可以让宿主机的目录和容器中的目录形成映射关系,实现共享数据。
数据卷的本质就是一个目录。
创建的数据卷都放在【/var/lib/docker/volumes/…】
3.2,创建数据卷
docker volume create 数据卷名称
3.3,查看数据卷信息
docker volume inspect 数据卷名称
3.4,查看全部数据卷
docker volume ls
3.5,删除数据卷
- 只能删除没有被容器引用的数据卷
- 删除全部:【docker volume prune】
- 删除指定的数据卷:【docker volume rm 数据卷名称】
3.6,创建容器时挂载数据卷
- 方法一:
- 先创建数据卷、再通过名称挂载
- 如果数据卷不存在,则会自动创建
- 方法二:
- 直接以目录的方式挂载
- 如果映射的宿主机目录不存在,则会自动创建
方法一例子:
============================================
docker run -d \
-p 3306:3306 \
–name mysql3306 \
-v mysql_conf:/etc/mysql/conf.d/ \
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7.25
============================================
docker run -d \
-p 3306:3306 \
–name mysql3306 \
-v mysql_conf:/etc/mysql/conf.d/ \ 【数据卷mysql_conf映射/etc/mysql/conf.d/】
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7.25
方法二例子:
==============================================
docker run -d
–name mysql3306
-p 3306:3306
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf
-v /tmp/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456
mysql:5.7.25================================================
docker run -d
–name mysql3306
-p 3306:3306
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf
-v /tmp/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456
mysql:5.7.25
四、自定义镜像Dockerfile
0,概述
1,语法
https://docs.docker.com/engine/reference/builder
2,例子
构建Java项目为自定义镜像并运行
0,上传资料中的 docker-demo.jar 到服务器
F:\java\上课视频4\后面资料\3-Docker\资料
1,编写 Dockerfile文件,名为Dockerfile,没有后缀
2,在Dockerfile文件写入下面内容:
FROM java:8-alpine COPY ./docker-demo.jar /tmp/docker-demo.jar EXPOSE 8090 ENTRYPOINT java -jar /tmp/docker-demo.jar - FROM java:8-alpine :基础镜像JDK - 将本地路径下的【docker-demo.jar】,拷贝到【/tmp/docker-demo.jar】 - 对外暴露接口【8090】 - 启动命令【ENTRYPOINT】
- 3,构建镜像
- 【docker build -t web:1.0 .】后面的【.】千万不能忘。
- 在Dockerfile文件所在的目录下运行构建镜像指令
- 4,运行容器
- 【docker run -d -p 8888:8090 --name myweb web:1.0】
- 5,测试,访问浏览器
- http://192.168.138.100:8888/hello/count
五、DockerCompose
1,概述
Docker官方的一个开源项目,可以实现容器编排部署。
比如可以通过DockerCompose一键开启mysql与tomcat
2,安装
- 1,上传 docker-compose 文件到 /usr/local/bin
- F:\java\上课视频4\后面资料\3-Docker\资料
- 2,授权
- chmod +x /usr/local/bin/docker-compose
- 3,测试是否安装成功
- docker-compose -v
3,编排部署mysql与tomcat
通过docker-compose.yml文件启动mysql与tomcat
3.1,编写文件docker-compose.yml
version: '3.7' # 这个不能随便写,与docker版本有关
services:
mysql: # 名称
image: mysql:5.7.25 # 镜像
container_name: mysql # 容器名
volumes: # 数据卷映射(最好使用文件)
- mysql_conf/my.cnf:/etc/mysql/conf.d/my.cnf
- mysql_data:/var/lib/mysql
environment: # 环境
- MYSQL_ROOT_PASSWORD=123456
ports: # 系统端口:容器端口
- 3306:3306
restart: always # 重启容器方式
tomcat:
image: tomcat:8.5.13
container_name: tomcat
volumes:
- /opt/webapps:/usr/local/tomcat/webapps
ports:
- 8080:8080
restart: always
3.2,运行容器
- 【docker-compose up -d】
- 必须在docker-compose.yml文件所在的目录或者子目录下运行
4,相关命令
- 运行:【docker-compose up -d】
- 停止、启动、重启:【docker-compose stop|start|restart [服务名]】
- 查看日志:【docker-compose logs -f [服务名]】
- 停止并删除容器:【docker-compose down】
六、搭建私服
1,使用docker-compose.yml
1.1,创建docker-compose.yml文件
version: '3.7'
services:
registry:
image: registry
volumes:
- ./registry-data:/var/lib/registry
ui:
image: joxit/docker-registry-ui:static
ports:
- 8080:80
environment:
- REGISTRY_TITLE=传智教育私有仓库
- REGISTRY_URL=http://registry:5000
depends_on:
- registry
1.2,配置私服
1,vi /etc/docker/daemon.json
2,{
“registry-mirrors”: [“https://p11xf841.mirror.aliyuncs.com”],
“insecure-registries”:[“http://192.168.138.100:8080”]
}3,重新加载配置文件
systemctl daemon-reload4,重启Docker
systemctl restart docker
1.3,启动
docker-compose up -d
1.4,测试
2,在私服上传或拉取镜像
- 打tag
- docker tag nginx:latest 192.168.138.100:8080/nginx:latest
- docker tag 镜像名:镜像版本 私服ip:私服端口/自己创建的名称
- 推送到私服
- docker push 192.168.138.100:8080/nginx:latest
- 从私服拉取
- docker pull 192.168.138.100:8080/nginx:latest