Docker 的安装、启动 和 基本用法
文章目录1.Docker的简介1.1 什么是虚拟化1.2什么是Docker1.3容器与虚拟机比较1.4Docker组件1.4.1Docker服务器与客户端1.4.2Docker镜像与容器1.4.3Registry(注册中心)2.Docker的安装与启动2.1安装Docker(1)检查版本(2)如果安装过请先卸载(3)安装依赖设置yum仓库(4)安装Docker(5)重启ContOS(6)验证是否安
文章目录
1.Docker的简介
学习目标:
掌握Docker基础知识,能够理解Docker镜像与容器的概念
完成Docker安装与启动
掌握Docker镜像与容器相关命令
掌握Tomcat、NGINX等软件的常用安装
掌握Docker迁移与备份相关命令
能够运用Dockerfile编写创建容器的脚本
能够搭建与使用Docker私有仓库
1.1 什么是虚拟化
在计算机中,虚拟化(英文:Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络及内存等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。这些资源的新虚拟部分是不受现有资源的架设方式、地域或物理组态所限制。一般所指的虚拟化资源包括计算能力和资料存储。
在实际的生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用问题,透明化底层物理硬件,从而最大化的利用物理硬件。对资源充分利用。
虚拟化技术种类很多,如:软件虚拟化、硬件虚拟化、内存虚拟化、网络虚拟化、桌面虚拟化、服务虚拟化、虚拟机等。
1.2什么是Docker
Docker是一个开源项目,诞生于2013年,最初是 dotCloud公司内部的一个业余项目。它基于Google公司推出的Go语言实现。项目后来加入了Linux基金会,遵从了Apache2.0协议,项目代码在GitHub上进行维护。
Docker自开源后受到广泛的关注和讨论,以至于dotCloud公司后来改名为Docker Inc。Redhat已经在其RHEL6.5中集中支持Docker;Google也在其Paas产品中广泛应用。
Saas : software as service
Paas : platform as service 平台即服务
Iaas : Infrastructure as service 基础设施即服务
Baas : Blockchain as service 后端即服务(delphi firemonkey)一套后台(c/s)管理 —> apk,ios 32 64操作系统
Docker项目的目标是实现轻量级的操作系统虚拟化解决方案。Docker的基础是Linux容器(LXC)等技术。
在LXC的基础上Docker进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作Docker的容器就像操作一个快速轻量级的虚拟机一样简单。
为什么选择Docker?
(1)上手快
用户只需要几分钟,就可以把自己的程序“Docker化”。Docker依赖于“写时复制”(copy-on-write)模型,使修改应用程序也非常迅速,可以说达到“随心所至,代码即改”的境界。
随后,就可以创建容器来运行应用程序了。大多数Docker容器只需要不到一秒钟即可启动。由于去除了管理程序的开销,Docker容器拥有很高的性能,同时同一台宿主机中也可以运行更多的容器,使用户尽可能的充分利用系统资源。
(2)职责的逻辑分类
使用Docker,开发人员只需要关心容器中运的行应用程序,而运维人员只需要关心如何管理容器。Docker设计的目的就是要加强开发人员写代码的开发环境与应用程序要部署的生产环境一致性。从而降低那种“开发时一切正常,肯定是运维的问题(测试环境都正常,上线后出了问题就归结为肯定是运维的问题)”
(3)快速高效的开发生命周期
Docker的目标之一就是缩短代码从开发、测试到部署、上线运行的周期,让你的应用程序具备可移植性,易于构建,并易于操作。(通俗的说,Docker就像一个盒子,里面可以装很多物件,如果需要这些物件的可以直接将该大盒子拿走,而不需要从盒子中一件一件的取)
(4)鼓励使用面向服务的架构 SOA
Docker还鼓励面向服务的体系结构和微服务架构。Docker推荐单个容器只允许一个应用程序或进程,这样就形成了一个分布式的应用程序模型,在这种模型下,应用程序或者服务都可以表示为一系列内部互联的容器,从而使分布式部署应用程序,扩展或调试应用程序都变得非常简单,同时也提高了程序的内省性。(当然,也可以在一个容器中运行多个应用程序)
1.3容器与虚拟机比较
下面的图片比较了Docker和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统的方式则是在硬件层面实现。
与传统的虚拟机相比,Docker的优势体现为启动速度快、占用体积小。
1.4Docker组件
1.4.1Docker服务器与客户端
Docker是一个客户端-服务器(C/S)架构程序。Docker客户端只需要向Docker服务器或守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具docker已经一整套RESTful API。可以在同一台宿主机上运行Docker守护进程和客户端,也可以从本地的Docker客户端连接到运行在另一台宿主机上的远程Docker守护进程。
1.4.2Docker镜像与容器
镜像是构建Docker的基石。用户基于镜像来运行自己的容器。镜像也是Docker生命周期中的“构建”部分。镜像是基于联合文件系统的一种层式结构,由一系列指令一步一步构建出来。例如:
添加一个文件;
执行一个命令;
打开一个窗口。
一个镜像可以当做容器的“源代码”。镜像体积很小,非常“便携”,易于分享、存储和更新。
Docker可以帮助我们构建和部署容器,我们只需要把自己的应用程序或者服务打包放进容器即可。容器是具有镜像启动起来的,容器中可以运行一个或多个进程。我们可以认为,镜像是Docker生命周期中的构建或者打包阶段,而容器则是启动或者执行阶段。容器基于镜像启动,一旦容器启动完成后,我们就可以登录到容器中安装自己需要的软件或者服务。
所以Docker容器就是:
一个镜像格式;
一系列标准操作;
一个执行环境。
Docker借鉴了标准集装箱的概念。标准集装箱将货物运往世界各地,Docker将这个模型运用到自己的设计中,唯一不同的是:集装箱运输货物,而Docker运输软件。
和集装箱一样,Docker在执行上述操作时,并不关心容器中到底装了什么,它不管是web服务器还是数据库,或者是应用程序服务器什么的。所有的容器都按照相同的方式将内容“装载”进去。
Docker也不关心你要把容器运到何方:我们可以在自己的笔记本中构建容器,上传到Registry,然后下载到一个物理的或者虚拟的服务器来测试,再把容器部署到具体的主机中。像标准集装箱一样,Docker容器方便替换,可以叠加,易于分发,并且尽量通用。
1.4.3Registry(注册中心)
Docker用Registry来保存用户构建的镜像。Registry分为公共和私有两种。Docker公司运营公共的Registry叫做Docker Hub。用户可以在Docker Hub注册账号,分享并保存自己的镜像(说明:在Docker Hub下载镜像非常慢,可以自己构建私有的Registry)
2.Docker的安装与启动
2.1安装Docker
(1)检查版本
Docker 要求 CentOS 系统的内核版本高于 3.10,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker 。
通过 uname -r 命令查看你当前的内核版本
(2)如果安装过请先卸载
卸载Docker,旧版本docker没安装成功直接卸载掉。
(1)查看安装过的包:yum list installed | grep docker
本机安装过的旧版本:docker.x86_64
docker-client.x86_64
docker-common.x86_64
(2)删除安装的Docker相关的软件包:
yum -y remove docker.x86_64
yum -y remove docker-client.x86_64
yum -y remove docker-common.x86_64
(3)安装依赖设置yum仓库
安装依赖:
sudo yum install -y yum-utils
设置仓库:
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
(4)安装Docker
前三个最好都执行一下,后面一个是禁用命令,看个人需求
这些存储库包含在docker.repo
上面的文件中,但默认情况下处于禁用状态。您可以将它们与稳定存储库一起启用。以下命令启用夜间存储库。
sudo yum-config-manager --enable docker-ce-nightly
要启用测试通道,请运行以下命令:
sudo yum-config-manager --enable docker-ce-test
安装最新版本的Docker CE和containerd
sudo yum install docker-ce docker-ce-cli containerd.io
可以通过运行带有标志的命令来禁用每晚或测试存储库 。要重新启用它,请使用该标志。以下命令禁用夜间存储库。
sudo yum-config-manager --disable docker-ce-nightly
(5)重启网络
systemctl restart network ( CentOS 7 )
service network restart ( CentOS 6 )
(6)启动Docker
启动Docker
systemctl start docker
查看Docker状态
systemctl status docker
显示active说明Docker已经启动
(7)验证是否安装成功
docker version
安装成功
下载hell world
docker run hello-world
2.2Docker配置加速器
我们国内使用官方Docker Hub仓库实在是太慢了,很影响效率
进入到docker目录:
cd /etc/docker/
使用 ls 查看该目录下的文件,没有 daemon.json 就使用 touch daemon.json 创建一个文件。
使用命令 vi dameon.json 打开 dameon.json 文件
加入下面的数据:
腾讯云的服务器镜像:
{
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
如果你是docker-cn镜像那么请加入:
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
esc回车,按住shift+z+z,保存
加载配置,重启docker,启动Docker
加载配置
systemctl daemon-reload
重启Docker
systemctl restart docker
启动Docker
systemctl start docker
查看docker版本
docker version
2.3 Docker的启动与停止
systemctl命令是系统(centOS7+)服务管理指令.
启动docker:
systemctl start docker
停止docker:
systemctl stop docker
重启docker:
systemctl restart docker
查看docker状态:
systemctl status docker
开机启动:
systemctl enable docker
关闭开机启动:
systemctl disable docker
查看docker概要信息:
docker info
docker命令帮助:
docker --help
3.Docker常用命令
3.1镜像相关命令
3. 1. 1查看镜像
docker images
REPOSITORY: 镜像名称
TAG: 镜像标签
IMAGEID: 镜像ID
CREATED : 镜像的创建日期(不是获取该镜像的日期)
SIZE: 镜像的大小
这些镜像都是存储在docker宿主机的 /var/lib/docker 目录下
3.1.2搜索镜像
如果需要从网络中查找需要的镜像,可以通过以下命令搜索:
docker search [image_name]
比如:docker search mysql
NAME: 仓库名称
DESCRIPTION: 镜像描述
STARS: 用户评价,反应一个镜像的受欢迎程度
OFFICIAL:是否官方
AUTOMATED: 自动构建,表示镜像由Docker Hub自动构建流程创建的
3.1.3 拉取镜像
拉取镜像就是从中央仓库中下载镜像到本地
docker pull [image name]
例如,我要下载 mysql 的镜像
docker pull mysql
3.1.4 删除镜像
按镜像ID删除镜像
docker rmi 镜像ID
删除所有镜像
docker rmi `docker images -1`
删除镜像出现错误:
报出这个容器还在用着镜像
Error response from daemon: conflict: unable to delete d1165f221234 (must be forced) - image is being used by stopped container 33ff66e1a8f2
解决:
先使用命令删除该容器
docker rm 33ff66e1a8f2
在按镜像ID删除镜像
docker rmi 镜像ID
3.2 容器相关命令
3.2.1 查看容器
查看正在运行的容器
docker ps
查看所有容器
docker ps -a
查看最后一次运行的容器
docker ps -l
查看停止的容器
docker ps -f status=exited
3.2.2 创建与启动容器
创建容器常用的参数说明:
创建容器命令:
docker run
-i:表示运行容器
-t:表示容器启动后会进入命令行模式。
加入这两个参数后,容器创建后就能登录进去。即分配一个伪终端。
- - name:为创建的容器命名。
-v:表示目录映射关系(前者是宿主机目录,后者是要映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
-d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后,不会自动登录容器。如果只加-i -t 两个参数,创建后会登录到容器)。
-p:表示端口映射,前者是宿主机端口后者是容器内的映射端口,可以使用多个-p映射多个端口。
(1)交互方式创建容器
交互方式创建容器
docker run -it --name=容器名称 镜像名称:标签 /bin/bash
执行步骤:
列出本地镜像
docker images
显示当前正在运行的容器( 要为空 )
docker ps
显示所有状态的容器 (要为空)
docker ps -a
上述两个 ps 和 ps -a 命令显示有就使用命令 docker rm 镜像ID 进行删除
在执行交互方式创建容器
docker run -it --name=tomcat tomcat /bin/bash
/usr/local/tomact
是tomcat的目录
这时我们通过ps命令查看,发现可以看到启动的容器,状态为启动状态
退出当前容器:
exit
(2)守护方式创建容器
守护方式创建容器
docker run -id --name=容器名称 镜像名称:标签
执行步骤:
进入home目录
cd /home
查看目录下的文件,发现没有 webapps目录 ,使用命令添加
mkdir webapps
进入webapps目录
cd webapps
查看”当前工作目录“的完整路径
pwd
守护方式创建 tomcat 容器
docker run -id --name=tomcat -v /home/webapps:/usr/local/tomcat/webapps -p 8081:8080 tomcat
--name后面填容器别名 -v:表示目录映射关系(前者是宿主机目录,后者是要映射到宿主机上的目录) -p 外部访问端口 内部端口
查看防火墙是否开着,绿色表示开启了
systemctl status firewalld
更新防火墙规则:
firewall-cmd --reload
查看tomcat端口
firewall-cmd --list-ports
如果使用上述命令没有查到端口的话,使用以下命令
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-ports
如果想要删除端口,使用以下命令
firewall-cmd --zone=public --remove-port=8081/tcp --permanent
每次都更新防火墙规则,都需要重新更新:firewall-cmd --reload
,更新状态;
进入webapps目录下,创建一个网页用于,使用 mkdir ROOT
创建一个tomcat的根目录 ,在创建一个新文件 touch index.html
,输入 vi index.html
进入文件,也可以输入 vim index.html
进入文件, 前提是下载了 vim (文本编辑器),下载命令:yum install -y vim
输入vim index.html 进入index.html文件,按 a 添加数据,按Esc
返回输入**:wq** 保存
<html>
<head>
<meta http-equiv="Content-Type" content ="text/htnl;charset=utf-8">
<title>从docker容器启动tomcat</title>
</head>
<body>
看到这个页面,就说明docker容器tomcat启动成功了
</body>
</html>
在浏览器中输入ip地址加端口号就能进入了,前提是tomcat容器启动了,使用 docker ps
就可以查看启动的容器
登录守护式容器方式:
docker exec -it 容器名称(或者容器ID) /bin/bash
设置tomcat服务开机自启
在使用守护方式创建容器的命令里面加一个 --restart=always
docker run -id --name=tomcat -v /home/webapps:/usr/local/tomcat/webapps -p 8080:8080 --restart=always tomcat
Flag Description
no 不自动重启容器. (默认value)
on-failure 容器发生error而退出(容器退出状态不为0)重启容器
unless-stopped 在容器已经stop掉或Docker stoped/restarted的时候才重启容器
always 在容器已经stop掉或Docker stoped/restarted的时候才重启容器
使用 curl localhost:8080
获得页面
3.2.3 停止与启动容器
停止容器:
docker stop 容器名称(或者容器id)
启动容器:
docker start 容器名称(或者容器id)
3.2.4 文件拷贝
如果我们需要将文件copy到容器内可以使用cp命令
docker cp 宿主机文件或目录 容器名称:容器目录
列如:
docker cp index.html 17d188b91ccd:/usr/local/tomcat/webapps
也可以将文件从容器内copy出来
docker cp 容器名称:容器目录 需要copy到宿主机的文件或目录
列如:
docker cp tomcat:/usr/local/tomcat/webapps/index.html /home/
3.2.5 目录挂载
我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器。
创建容器添加-v参数, -v后边是 宿主机目录:容器目录,例如:
docker run -di -v /usr/local/mythml:/usr/local/myhtml --name=mycentos3 centos:7
如果共享的是多级的目录,可能会出现权限不足的提示。这是因为CentOS7中的安全模块selinux把权限禁用掉了,我们需要添加参数 --privileged=true
来解决挂载的目录没有权限的问题。
3.2.6 查看容器ip地址
我们可以通过以下命令查看容器运行的各种数据
docker inspect 容器名称(或者容器id)
也可以直接执行下面的命令直接输出IP地址
docker inspect --format=‘{{.NetworkSettings.IPAddress}}’容器名称(或者容器ID)
3.2.7 删除容器
删除指定的容器
docker rm 容器名称(或者容器ID)
4. 应用部署
4.1 Mysql部署
(1)搜索MySQL镜像
docker search mysql
尽量下载官方的mysql,OFFICIAL下面是[ OK ] 就说明是官方的
(2) 拉取MySQL镜像
docker pull mysql
(3) 创建容器
docker run -di --name=mysqlNew -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql
--name后面填容器别名 -p 代码端口映射,格式为: 宿主机端口:容器运行端口
-e 代码添加环境变量 MYSQL_ROOT_PASSWORD是MySQL root是密码 账号默认为root
(4) 进入mysql容器
docker exec -it mysqlNew /bin/bash
(5) 登录mysql
mysql -u root -p
(6) 远程登录mysql
连接宿主机的ip,指定端口为宿主机映射端口3306
4.2 Tomcat部署
(1)搜索MySQL镜像
docker search tomcat
尽量下载官方的tomcat,OFFICIAL下面是[ OK ] 就说明是官方的
(2)拉取镜像
docker pull tomcat
(3) 创建容器
创建容器 -p 表示端口映射
docker run -id --name=tomcat -v /home/webapps:/usr/local/tomcat/webapps -p 8081:8080 tomcat
tomcat容器的创建详解在守护方式创建容器那
4.3 Nginx部署
(1)搜索Nginx镜像
docker search nginx
尽量下载官方的nginx,OFFICIAL下面是[ OK ] 就说明是官方的
(2)拉取镜像
docker pull nginx
(3)创建NGINX容器
docker run -di --name=mynginx -p 80:80 nginx
4.4 Reids 部署
(1)搜索Redis镜像
docker search reids
尽量下载官方的reids,OFFICIAL下面是[ OK ] 就说明是官方的
(2)拉取镜像
docker pull redis
(3)创建容器
docker run -di --name=myredis -p 6379:6379 redis
5. 迁移与备份
5.1 容器保存为镜像
我们可以通过以下命令将容器保存为镜像
docker commit 17d188b91ccd mytomcat:5.14
mytomcat:创建镜像的名称 5.14:镜像标签
5.2 镜像备份
我们可以通过以下命令将镜像保存为tar文件
docker save -o mytomcat.tar mytomcat:5.14
5.3 镜像恢复与迁移
docker load -i mytomcat.tar
-i 输入的文件
6. Dockfile
6.1 什么是Dockerfile
Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。
- 对于开发人员:可以为开发团队提供一个完全一致的开发环境;
- 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了;
- 对于运维人员:在部署时,可以实现应用的无缝移植。
6.2 常用命令
命令 | 作用 |
---|---|
FROM image_name:tag | 定义了使用哪个基础镜像启动构建流程 |
MAINTAINER user_name | 声明镜像的创建者或维护者信息 |
ENV key value | 设置环境变量(可以写多条) 格式为:ENV key value 例如:ENV JAVA_HOME /path/to/java |
RUN command | 是Dockerfile的核心部分(可以写多条) 格式:RUN 在shell终端运行,使用这种格式,就像直接在命令行中输入命令一样。 RUN [“executable”,”param1”,”param2”] 使用exec 执行,这种方式类似于函数调用。该方式必须使用双引号,不能使用单引号,因为该方式会被转换成JSON数组 |
ADD source_dir/file dest_dir/file | 将宿主机的文件复制到容器内,如果是压缩文件,将会在复制后自动解压 |
COPY source_dir/file dest_dir/file | 和ADD相似,但是如果是压缩文件并不能解压 |
WORKDIR path_dir | 设置工作目录,也可说是切换目录指令,类似cd命令,写在该指令后的RUN,CMD以及ENTRYPOINT指令都将该目录作为当前目录,并执行相应命令 |
ARG 设置构建参数 | ARG指令用于设置构建参数,类似EVN,和ENV不同的是,ARG设置的是构建时的环境变量,在容器运行时是不会存在这些变量的 |
CMD 容器启动命令 | 用于为执行容器提供默认值。每个Dockerfile只有一个CMD命令,如果指定多个CMD命令,那么只有最后一条会被执行,如果启动容器时指定了运行的命令,则会覆盖CMD指定的命令。支持3种格式: CMD [“executable”,”param1”,”param2”] (推荐) CMD “param1”,”param2” 实例:CMD echo “this is a test.” | wc - |
ENTRYPOINT入口点 | ENTRYPOIN和CMD命令的目的一样,都是指定docker容器启动时执行的命令,可以多次设置,但是只有最后一个有效 |
EXPOSE声明暴露的端口 | EXPOSE指令用于声明在运行时容器提供服务的端口,格式为: EXPOSE […] 可以声明暴露多个端口 需要注意的是,这只是一个声明,运行时并不会因为该声明就打开相应的端口。该指令的作用主要是帮助镜像使用者理解该项服务的守护端口;其次是当运行时使用随机映射时,会自动映射EXPOSE的端口。 |
6.3 使用脚本创建镜像
(1)创建Dockerfile文件
#创建springDocker目录
mkdir springDocker
#通过Xftp工具导入项目jar包
#创建Dockerfile文件
touch Dockerfile
#进入Dockerfile文件
vim Dockerfile
#依赖镜像名称或ID
from java:8
#切换工作目录
workdir /home
#ADD是相对路径的jar,把java添加到容器总
add spring_bood_0514.jar /home
#EXPOSE声明暴露的端口
expose 8080
#和CMD命令的目的一样,都是指定docker容器启动时执行的命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/home/spring_bood_0514.jar"]
语法详解在上面 6.2常用命令
(2)执行命令构建镜像
docker build -t="springbood:1.0" .
. 代表当前目录,Dockerfile文件名字必须首字母大写
(3)创建容器
docker run -di --name=springbood -p 8080:8080 springbood:1.0
(4)启动日志信息
#查看当前正在运行的容器
docker ps
#启动日志信息
docker logs springbood
(5)测试访问
7. Docker私有仓库
7.1 私有仓库搭建与配置
(1)拉取私有仓库镜像
docker pull registry
(2)启动私有仓库容器
docker run -di --name=registry -p 5000:5000 registry
(3)打开浏览器输入地址http://宿主机ip:5000/v2/_catalog看到{“repositories”:[]} 表示私有仓库搭建成功并且内容为空
(4)修改daemon.json
vi /etc/docker/daemon.json
添加以下内容,保存退出
"insecure-registries":["宿主机ip:5000"]
前面要加逗号 , 隔开
此步用于让docker信任私有仓库地址
(5)重启docker服务
systemctl restart docker
7.2镜像上传至私有仓库
(1) 标记镜像为私有仓库的镜像
docker tag springbood:1.0 宿主机ip:5000/springbood:1.0
比如:
docker tag springbood:1.0 192.168.192.10:5000/springbood:1.0
(2) 上传标记的镜像
docker push 宿主机ip:5000/springbood:1.0
比如:
docker push 192.168.192.10:5000/springbood:1.0
7.3拉取私有仓库的镜像
docker pull 宿主机ip:5000/springbood:1.0
比如:
docker pull 192.168.192.10:5000/springbood:1.0
这个和你提交的路径是一样的
7.4查看私有镜像仓库内容
curl http://宿主机ip地址:5000/v2/_catalog
比如:
curl http://192.168.192.10:5000/v2/_catalog
8. 使用Maven插件构建Docker镜像
Maven是一个强大的项目管理与构建工具。如果可以使用Maven构建Docker镜像,工作就能得到进一步的简化。
dockerfile-maven-plugin,该maven插件可以实现有java源代码直接到docker镜像,配置了dockerfile-maven-plugin插件的 maven 工具就像是一个管道,一端输入Java源代码,另一端直接输出docker镜像。
在 dockerfile-maven-plugin 插件出现之前,还有一个maven插件是docker-maven-plugin,是由同一个作者创造,作者明确表示推荐使用dockerfile-maven-plugin,并会 持续升级;而docker-maven-plugin不在添加任何新功能,只接受修复bug。两个插件的设计思想是有差别的,前者需要独立编写Dockerfile文件,后者允许没有Dockerfile文件,所有的docker相关配置都写在pom文件的plugin中,这样使maven插件显得很笨重,并且如果脱离了这个maven插件还得重写编写Dockerfile,不够灵活。
因此,推荐使用maven插件:dockerfile-maven-plugin。
8.1 IDEA连接远端的Docker服务器:
1.修改/usr/lib/systemd/system/docker.service服务文件
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
2.修改完服务文件后:
Systemctl daemon-reload;
Systemctl start docker;
3.Idea连接docker
4.docker方式部署dubbo服务提供者
4.1编写Dockerfile文档
FROM java:8
WORKDIR /
ADD target/backstageprovider-assembly.tar.gz /
EXPOSE 20880
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/backstageprovider/lib/dubbo_provider-1.0-SNAPSHOT.jar"]
4.2 像运行普通java类一样在idea中运行Dockfile
8.2具体操作方法
(1) 首先本地要安装docker环境。
(2) 在maven的pom文件中配置build的插件。
<properties>
<dockerfile.maven.version>1.4.0</dockerfile.maven.version>
<docker.registry.name.prefix>192.168.6.37:80/galaxy</docker.registry.name.prefix></properties>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile.maven.version}</version>
<dependencies>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${docker.registry.name.prefix}/${project.artifactId}</repository>
<tag>${project.version}</tag>
<username>username</username>
<password>password</password>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
(3) 标准的Dockerfile放在classpath的根目录下。
(4) 执行maven命令:mvn clean package。
从的配置中可以看到,在执行maven命令的时候会默认执行docker的build和push。
单独执行dockerfile操作的maven命令是:mvn dockerfile:build 和 mvn dockerfile:push等。中配置docker镜像的仓库的地址等。
8.3 docker注册dubbo服务ip问题解决
1、A service使用docker部署,注册到zk上的ip地址为172.17.0.5(这是容器内部的ip地址)
2、B service从zk取到A service的地址为A service容器内的地址
3、当A service和B service不在同一个主机时,就出现无法互通
要解决上述的问题,主要就是将docker容器管理的应用注册到zk上的地址弄成宿主机的ip地址。经过查找资料,尝试了两种解决方案。
1、通过docker网络模式为主机模式(默认网桥)
docker run -d --name xxx –net “host” --restart=always xxx
这里可以不用配置端口映射,并且我们用docker ps也看不到该容器的绑定的端口
2、通过-e 设置一些dubbo注册到注册中心的ip地址,可通过下面参数指定
DUBBO_IP_TO_REGISTRY — 注册到注册中心的IP地址
DUBBO_PORT_TO_REGISTRY — 注册到注册中心的端口
DUBBO_IP_TO_BIND — 监听IP地址
DUBBO_PORT_TO_BIND — 监听端口
假设我们的宿主机的ip是29.36.100.95
那么在根据镜像创建容器的时候,我们可以通过-e设置DUBBO_IP_TO_REGISTRY的值,下面是我的测试环境的创建设置语句
docker run -d --name xxx -e DUBBO_IP_TO_REGISTRY=29.36.100.95 -p 10010:10010 xxx
配置成功后,可以通过dubbo控制台,或者直接读取zk的节点信息,可以看到注册到zk上的ip地址为宿主机ip地址
9. 使用Docker Compose编排微服务
微服务架构的应用系统一般包括若干个微服务,每个微服务一般都会部署多个实例。如果每个微服务都要手动启停,那么效率很低,维护量很大。
下面我们讨论如何使用docker compose来轻松、高效地管理容器。
9.1 安装Docker Compose
Docker Compose 有多种安装方式,可以通过Shell、pip以及将Compose作为容器安装等。我们采用shell方式安装。
- 通过以下命令自动下载并安装适应系统版本的Compose:
curl -L “https://github.com/docker/compose/releases/download/1.10.0/docker-compose-$(uname -s)-$(uname -m)” -o /usr/local/bin/docker-compose
- 为安装脚本添加可执行权限:
chmod +x /usr/local/bin/docker-compose
这样,Compose就安装完成。
可以使用以下命令测试安装结果:
docker-compose --version
输出以下内容:
docker-compose version 1.10.0, build 4bdf61a
说明Compose安装成功。
9.2 安装Compose命令补全工具
成功安装Compose后,当输入docker-compose并按下Tab键时,Compose并没有补全命令。要想使用Compose的命令补全功能,需要安装命令补全工具。
执行以下命令,即可安装命令补全工具:
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
安装完成重新登录系统,输入docker-compose并按下tab键,Compose就可以自动补全命令了。
9.3 Docker Compose 快速入门
9.3.1 基本步骤
使用Docker Compose大致有3个步骤:
- 使用Dockerfile(或其他方式)定义应用程序环境,以便在任何地方重现该环境。
- 在docker-compose.yml文件中定义组成应用程序的服务,以便各个服务在一个隔离的环境中一起运行。
- 运行docker-compose up 命令,启动并运行整个应用程序。
9.3.2 入门实例
下面以eureka服务为例讲解compose的基本步骤。
1.使用mvn clean package 命令打包项目,获得xxx-eureka.jar
2.在xxx-eureka.jar所在路径创建Dockerfile文件,并添加如下内容:
FROM java:8
VOLUME /tmp
ADD xxx-eureka.jar app.jar
RUN bash -c ‘touch /app.jar’
EXPOSE 9000
ENTRYPOINT [“java”,”-Djava.security.egd=file:/dev/./urandom”,”-jar”,”/app.jar”]
3.在xxx-eureka.jar所在路径创建文件docker-compose.yml,在其中添加如下内容:
version: ‘3’
services:
eureka: #指定服务名称
build: . #指定dockerfile所在路径
ports:
- “8761:8761” # 指定端口映射,类似docker run的-p选项,这里是字符串形式
4.在docker-compose.yml所在路径执行以下命令:
docker-compose up
Docker compose 会自动构建镜像并使用镜像启动容器。也可以使用docker-compose up -d 后台启动并运行容器。
5.访问http://宿主机IP:8761/, 即可访问Eureka Server。
9.3.3 工程、服务、容器
Docker Compose 将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程(默认为docker-compose.yml所在目录的目录名称)。一个工程可研包含多个服务,每个服务中定义了容器运行的镜像、参数和依赖,一个服务可研包括多个容器实例。
上面实例中,工程名称是docker-compose.yml所在的目录名。该工程包含一个服务。服务名称是eureka。
9.4 docker-compose.yml常用配置
Docker-compose.yml 是Compose的默认模板文件。该文件有多种格式,例如Version 1 file format、Version 2 file format、Version 2.1 file format、Version 3 file format等。其中,Version 1 file format被弃用,Version2.X及Version 3.X 基本兼容。
我们使用Version 3 file format 常用配置。
9.4.1 build
配置构建时的选项,Compose会利用它自动构建镜像。Build的值可以是一个路径,例如:
build: ./dir
也可以是一个对象,用于指定Dockfile和参数,例如:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
9.4.2 commond
覆盖容器启动后默认执行的命令,示例:
command: bundle exec thin -p 3000
也可以是一个List,类似Dockerfile中的CMD命令,格式如下:
command: [bundle,exec,thin,-p,3000]
9.4.3 dns
配置dns服务器。可以是一个值,也可以是一个列表。示例:
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
9.4.4 dns_search
配置DNS的搜索域,可以是一个值,也可以是一个列表。示例:
dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com
9.4.5 environment
环境变量设置,可以使用数组或字典两种方式。示例:
environment:
RACK_ENV: development
SHOW: ‘true’
SESSION_SELECT:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
9.4.6 Env_file
从文件中获取环境变量,可以指定一个文件路径或路径列表。如果通过docker-compose -f FILE指定了Compose文件,那么evn_file中的路径是Compose文件所在目录的相对路径。使用environment指定的环境变量会覆盖evn_file指定的环境变量。示例:
env_file: .env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
9.4.7 expose
暴露端口,只将端口暴露给连接的服务,而不暴露给宿主机。示例:
expose:
- “3000”
- “8000”
9.4.8 external_links
连接到docker-compose.yml外部的容器,甚至并非Compose管理的容器,特别是提供共享或公共服务的容器。格式跟links类似,例如:
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
9.4.9 image
指定镜像名称或镜像ID, 如果本地不存在该镜像,Compose会尝试下载该镜像。示例:
image: java
9.4.10 links
连接到其他服务的容器。可以指定服务名称和服务别名(SERVICE:ALIAS),也可以只指定服务名称。例如:
web:
links:
- db
- db: database
- redis
9.4.11 network_mode
设置网络模式。示例:
network_mode: “bridge”
network_mode: “host”
network_mode: “none”
network_mode: “service:[service name]”
network_mode: “container:[container name/id]”
9.4.12 ports
暴露端口信息,可以使用HOST:CONTAINER格式,也可以只指定容器端口(此时宿主机将数据选择端口),类似于docker run -p
需要注意的是,当使用HOST:CONTAINER格式映射端口时,容器端口小于60将得到错误的接口,因为yaml会把xx:yy的数组解析为60进制。因此建议使用字符串的形式。示例:
ports:
- “3000”
- “3000-3005”
- “8000:8000”
- “9090-9091:8080-8081”
- “49100:22”
- “127.0.0.1:8001:8001”
- “127.0.0.1:5000-5010:5000-5010”
9.4.13 volumes
卷挂在路径设置。可以试着宿主机路径(HOST:CONTAINER),也可以指定访问模式(HOST:CONTAINER:ro). 示例:
volumes:
#指定路径由引擎创建卷
- /var/lib/mysql
#指定绝对路径映射
- /opt/data:/var/lib/mysql
#路径在主机上,关联到Compose文件
- ./cache:/tmp/cache
#用户路径关联
- ~/configs:/etc/configs/:ro
#卷命名
-datavolume:/var/lib/mysql
9.5 Docker-compose 常用命令
和docker一样,docker-compose命令也有喝多选项。
build:构建或重新构建服务。服务被构建后将以project_service的形式标记。
help:查看指定命令的帮助文档。Docker-compose所有命令的版主文档都可以通过该命令查看。
docker-compose help COMMAND
kill: 通过发送SIGKILL信号停止指定服务的容器。示例:
docker-compose kill eureka
logs: 查看服务的热值输出。
port: 打印绑定的公共端口。示例:
docker-compose port eureka 8761
这样就可以输出eureka服务8761端口所绑定的公共端口。
ps:列出所有容器。示例:
docker-compose ps
也可以列出指定服务的容器,示例:
docker-compose ps eureka
pull: 下载服务镜像。
rm: 删除指定服务的容器。示例:
docker-compose rm eureka
run: 在一个服务商执行一个命令。示例
docker-compose run web bash
这样即可以启动一个web服务,同时执行bash命令
scale:设置指定服务运行容器的个数,以service=num的形式指定。示例:
docker-compose scale user=3 movie=3
start:启动指定服务已存在的容器。示例:
docker-compose start eureka
stop:停止正在运行的容器。
up:构建、创建、重新创建、启动,连接服务的相关容器。所有连接的服务都会启动,除非它们已经运行。
docker-compose up命令会聚合所有容器的输出,当命令退出时,所有容器都会停止。使用docker-compose up -d 可在后台启动并运行说有容器。
9.6 Docker compose 网络设置
9.6.1 基本概念
默认情况下,Compose会为应用创建一个网络,服务的每个容器都会加入到该网络中。这样,容器就可以被该网络中的其他容器访问,不仅如此,该容器还能以服务名称作为hostname被其他容器访问。
默认情况下,应用程序的网络名称基于compose的工程名称,而项目名称基于docker-compose.yml所在目录的名称。如需修改工程名称,可以使用-project-name标识或COM-POSE_PROJECT_NAME环境变量。
假如一个应用程序在名为myapp的目录中,并且docker-compose.yml如下所示:
version: ‘3’
services:
web:
build: .
ports:
- “8000:8000”
db:
Image: postgres
当运行docker-compose up时,将执行以下步骤:
- 创建一个名为myapp_default的网络;
- 使用web服务的配置创建容器,它以“web”这名称加入网络myapp_default;
- 使用db服务的配置创建容器,它以“db”这个名称加入网络myapp_default.
容器间可使用服务名称(web或db)作为hostname相互访问。例如:web这个服务可以使用postgres://db:5432访问db容器
9.6.2 更新容器
当服务的配置发生更改时,可以使用docker-compose up 命令更新配置。
此时,Compose会删除旧的容器并创建新的容器。新容器会以不同的IP地址加入网络,名称保持不变。任何指向旧容器的链接都会被关闭,容器会重新找到新容器并链接上。
9.6.3 Links
默认情况下,服务直接可使用服务名称相互访问。Links允许定义一个别名,从而使该别名访问其他服务。示例:
version: ‘3’
services:
web:
build: .
links:
- “db:database”
db:
image: postgres
这样web服务就可以使用db或database作为hostname访问db服务了。
9.6.4 指定自定义网络
一些场景下,默认的网络配置满足不了我们的需求,此时可以使用networks命令自定义网络。networks命令允许创建更加复杂的网络拓扑并指定自定义网络驱动和选项。不仅如此,还可以使用networks将服务连接到不是由compose管理的外部创建的网络。
如下,定义了两个自定义网络:
version: ‘3’
services:
proxy:
build: ./proxy
networks:
- front
app:
build: ./app
networks:
- front
- back
db:
Image: postgres
networks:
- back
networks:
front:
driver: custom-dirver-1
back:
dirver: custom-criver-2
driver_opts:
foo: “1”
bar: “2”
其中,proxy服务与db服务隔离,两者分别使用自己的网络,app服务可与两者通信。使用networks命令可以方便实现服务间的网络隔离与连接。
9.6.5 配置默认网络
除了自定义网络外,也可以为默认网络自定义配置。
version: ‘3’
services:
web:
build: .
ports:
- “8000:8000”
db:
image: postgres
networks:
default:
driver: custom-driver-1
这样就可以为应用指定自定义的网络驱动。
9.6.6 使用已经存在的网络
一些场景下,并不需要创建新的网络,只需要加入已存在的网络,此时可以使用external选项。示例:
networks:
default:
external:
name: my-pre-existing-network
9.7 综合实战
使用docker compose 编排Spring Cloud 微服务
编排微服务列表
微服务名称 项目微服务角色
Discovery-eureka 服务发现组件
Provider-user 服务提供者
consumer 服务消费者
Geteway-zuul 服务网关
Hystrix-turbine Hystrix聚合监控工具
Hystrix-dashboard Hystrix监控界面
9.7.1 编写代码
1.使用Maven插件构建Docker镜像,在各个项目的pom.xml中添加一下内容
<!-- 添加docker-maven插件 -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>itmuch/${project.artifactId}:${project.version}</imageName>
<baseImage>java</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
由配置可知,构建出来的镜像名称是itmuch/各个微服务的artifactId:各个微服务的版本,例如:discovery-eureka:0.0.1-SNAPSHOT
2.之前各个项目配置的注册中心
eureka.client.serviceUrl.defaultZone的值是http://localhost:8761/eureka/ . 由于Docker默认的网络模式是bridge,各个容器的IP地址不相同,因此使用http://localhost:8761/eureka/ 满足不了需求。可为Eureka Server所在的容器配置一个主机名(如:discover),并让各个微服务使用主机名访问Eureka Server。
示例:
eureka:
client:
serviceUrl:
defaultZone: http://discovery:8761/eureka/
3.在每个项目的根目录执行以下命令,构建Docker镜像
mvn clean package docker:build
4.编写docker-compose.yml
version: '3' # 表示该docker-compose.yml文件使用的是Version 2 file format
services: # Version 2 file format的固定写法,为project定义服务。
microservice-discovery-eureka: # 指定服务名称
image: itmuch/microservice-discovery-eureka:0.0.1-SNAPSHOT # 指定服务所使用的镜像
ports: # 暴露端口信息
- "8761:8761"
microservice-provider-user:
image: itmuch/microservice-provider-user:0.0.1-SNAPSHOT
links: # 链接到microservice-discovery-eureka,这边使用的是SERVICE:ALIAS的形式
- microservice-discovery-eureka:discovery
microservice-consumer-movie-ribbon-hystrix:
image: itmuch/microservice-consumer-movie-ribbon-hystrix:0.0.1-SNAPSHOT
links:
- microservice-discovery-eureka:discovery
microservice-gateway-zuul:
image: itmuch/microservice-gateway-zuul:0.0.1-SNAPSHOT
links:
- microservice-discovery-eureka:discovery
microservice-hystrix-dashboard:
image: itmuch/microservice-hystrix-dashboard:0.0.1-SNAPSHOT
links:
- microservice-discovery-eureka:discovery
microservice-hystrix-turbine:
image: itmuch/microservice-hystrix-turbine:0.0.1-SNAPSHOT
links:
- microservice-discovery-eureka:discovery
执行以下命令启动项目:
docker-compose up
然后查看eureka server UI界面测试微服务是否能够正常运行。
5.简化Compose描述文件编写
在Version 2 file format的docker-compose.yml中,同一个Compose工程中的所有服务共享一个隔离网络,可以使用服务名称作为主讲名称来发现其他服务。因此docker-compose.yml文件可以简化成如下形式:
version: '3'
services:
discovery:
image: itmuch/microservice-discovery-eureka:0.0.1-SNAPSHOT
ports:
- "8761:8761"
microservice-provider-user:
image: itmuch/microservice-provider-user:0.0.1-SNAPSHOT
microservice-consumer-movie-ribbon-hystrix:
image: itmuch/microservice-consumer-movie-ribbon-hystrix:0.0.1-SNAPSHOT
microservice-gateway-zuul:
image: itmuch/microservice-gateway-zuul:0.0.1-SNAPSHOT
microservice-hystrix-dashboard:
image: itmuch/microservice-hystrix-dashboard:0.0.1-SNAPSHOT
microservice-hystrix-turbine:
image: itmuch/microservice-hystrix-turbine:0.0.1-SNAPSHOT
# 最简单的配置方式,等价于docker-compose.yml。
9.7.2 编排高可用的Eureka server
1.执行以下命令构建docker镜像
mvn clean package docker:build
2.编写docker-compose.yml,如下:
version: "3" # 表示使用docker-compose.yml的Version 3 file format编写
services:
microservice-discovery-eureka-ha1:
hostname: peer1 # 指定hostname
image: itmuch/microservice-discovery-eureka-ha:0.0.1-SNAPSHOT
links:
- microservice-discovery-eureka-ha2
ports:
- "8761:8761"
environment:
- spring.profiles.active=peer1
microservice-discovery-eureka-ha2:
hostname: peer2
image: itmuch/microservice-discovery-eureka-ha:0.0.1-SNAPSHOT
links:
- microservice-discovery-eureka-ha1
ports:
- "8762:8762"
environment:
- spring.profiles.active=peer2
## 该文件是最自然的写法,但无法正常使用。运行docker-compose up时,会报循环依赖的异常。
由文件内容可知,我们定义了两个服务:discovery-eureka-ha1和discovery-eureka-ha2 他们的hostname分别是peer1和peer2,通过links标签互相连接。
3.执行以下命令启动项目
docker-compose up
这个时候终端会输出异常:
ERROR: Circular dependency between ... and ...
从异常可知,写法存在循环依赖。也就是说links无法实现双向连接。
解决循环依赖的方案很多,使用ambassador pattern、使用外部DNS容器等。
version: "3"
services:
peer1: # 默认情况下,其他服务可使用服务名称连接到该服务。对于peer2节点,它需连接http://peer1:8761/eureka/,因此,我们可配置该服务的名称为peer1。
image: itmuch/microservice-discovery-eureka-ha:0.0.1-SNAPSHOT
ports:
- "8761:8761"
environment:
- spring.profiles.active=peer1
peer2:
image: itmuch/microservice-discovery-eureka-ha:0.0.1-SNAPSHOT
hostname: peer2
ports:
- "8762:8762"
environment:
- spring.profiles.active=peer2
## 使用Compose编排高可用的Eureka Server。
9.7.3 编排高可用Spring cloud 微服务集群及动态伸缩
使用Docker compose 编排Spring Cloud微服务,所有微服务节点都是高可用。
编排微服务列表
微服务名称 项目微服务角色
Discovery-eureka-ha 服务发现组件
Provider-user 服务提供者
consumer 服务消费者
Geteway-zuul 服务网关
Hystrix-turbine Hystrix聚合监控工具
对微服务进行改造
1.由于使用了discovery-eureka-ha 高可用服务发现(注册中心),需要将所有微服务的eureka.client.serviceUrl.defaultZone属性修改为如下内容:
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
2.在每个项目的根目录,执行以下命令构建Docker镜像。
mvn clean package docker:build
3.编写docker-compose.yml
version: "3"
services:
peer1:
image: itmuch/microservice-discovery-eureka-ha:0.0.1-SNAPSHOT
ports:
- "8761:8761"
environment:
- spring.profiles.active=peer1
peer2:
image: itmuch/microservice-discovery-eureka-ha:0.0.1-SNAPSHOT
hostname: peer2
ports:
- "8762:8762"
environment:
- spring.profiles.active=peer2
microservice-provider-user:
image: itmuch/microservice-provider-user:0.0.1-SNAPSHOT
microservice-consumer-movie-ribbon-hystrix:
image: itmuch/microservice-consumer-movie-ribbon-hystrix:0.0.1-SNAPSHOT
microservice-gateway-zuul:
image: itmuch/microservice-gateway-zuul:0.0.1-SNAPSHOT
microservice-hystrix-turbine:
image: itmuch/microservice-hystrix-turbine:0.0.1-SNAPSHOT
4.执行以下命令启动项目
docker-compose up
测试各微服务是否正常
5.执行以下命令,为各个微服务动态扩容。让除了Eureka Server 以外的所有微服务都启动3个实例。
docker-compose scale provider-user=3 consumer=3 gateway-zuul=3 hystrix-turbine=3
查看注册中心eureka的UI界面检查指定的微服务是否启动了指定的数量。
更多推荐
所有评论(0)