当前位置: 代码迷 >> 综合 >> idea使用docker构建Springboot服务swarm+overlay
  详细解决方案

idea使用docker构建Springboot服务swarm+overlay

热度:80   发布时间:2024-01-13 07:44:41.0

  • 1. 需要探讨的内容
  • 2. 常用命令(可略过)
    • 2.1. Linux开防火墙端口
    • 2.2. docker服务没有启动
  • 3. 使用IDEA在vm docker中快速部署eureka-server
    • 3.1. 虚拟机,2个
    • 3.2. docker环境,配置远程访问
    • 3.3. idea,安装docker插件
    • 3.4. idea,编写eureka-server代码
    • 3.5. idea,改写pom复制jar包到指定目录
    • 3.6. idea,配置docker
    • 3.7. idea,运行,在目标机器构建容器
  • 4. 在两个vm docker上部署sc集群
    • 4.1. docker网络知识
    • 4.2. 避坑命令 - 开docker端口
    • 4.3. 创建swarm集群
    • 4.4. 创建overlay网络
    • 4.5. 部署sc服务
      • 4.5.1. 部署eureka-server
      • 4.5.2. 部署service-provider
      • 4.5.3. 确认vm2 docker中的service-provider是否可以注册到vm1 docker中的eureka-server
      • 4.5.4. 考虑在vm1上部署一个service-consumer
    • 4.6. 部署sc服务结论,swarm与overlay

1. 需要探讨的内容

  • 如何在vm中部署一个springboot jar包应用
  • 在vm1中部署注册中心eureka,在vm2中部署service-provider
  • 分在2个vm中的服务是否可以互相访问?
  • 在vm1中部署service-consumer,来访问vm2中的service-provider

2. 常用命令(可略过)

2.1. Linux开防火墙端口

firewall-cmd --permanent --zone=public --add-port=8888/tcp
systemctl restart firewalld.service

过程中不要关闭防火墙,不然有些场景验证不出来,待生产配置的时候会各种报错。

2.2. docker服务没有启动

[root@localhost ~]# docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
[root@localhost ~]# systemctl restart docker

3. 使用IDEA在vm docker中快速部署eureka-server

考虑的场景是在做原型,不是生产部署,所以暂时没有集成工具如Jenkins。

传统的思路,在idea里编写eureka server,打jar包,上传到vm,制作镜像、容器、启动容器。

缺点:修改代码、打包、上传、制作、启动比较繁琐,不适合原型测试。

考虑:使用idea,一键将代码打包、制作镜像、上传并启动。

参考:为了解决这个问题,参考了https://www.jianshu.com/p/0dcc2e43963b 下文也会一步步来搭建环境

3.1. 虚拟机,2个

我这里安装的2个vm,ip地址分别是172.18.100.129和172.18.100.66,centos7

3.2. docker环境,配置远程访问

开启docker服务,开启tcp端口,操作如下:

sudo vim /lib/systemd/system/docker.service

找到如下配置

ExecStart=/usr/bin/dockerd

修改为

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

重启docker网络

sudo systemctl daemon-reload 
sudo systemctl restart docker

测试

[root@localhost ~]# curl http://localhost:2375/verion
{
    "message":"page not found"}

能够看到这个也是OK的,有的是可以看到具体的版本信息

记得开2375端口防火墙,2个vm都要开

3.3. idea,安装docker插件

具体的docker配置在后面,不着急配

3.4. idea,编写eureka-server代码

在创建eureka-server之前,有必要了解一下你要做demo的springcloud与springboot版本的关系

这里测试,我们用的SpringCloud是Hoxton.SR5,Springboot是2.3.1.RELEASE

有一个系列文章写的还行,比较简洁,当比较熟练的就直接照抄:https://my.oschina.net/mdxlcj/blog/2995192

至此,相当于是普通的eureka-server工程就创建好了,下面是跟idea的docker插件结合,来实现一键从idea部署到vm的过程

3.5. idea,改写pom复制jar包到指定目录

在项目的pom.xml文件中加入以下代码:

<!--复制jar包到指定目录-->
<plugin><artifactId>maven-antrun-plugin</artifactId><executions><execution><id>gen-webadmin</id><phase>package</phase><configuration><tasks><copy todir="docker" file="target/${project.artifactId}-${project.version}.${project.packaging}" /></tasks></configuration><goals><goal>run</goal></goals></execution></executions>
</plugin>

在项目根目录下建立一个docker文件夹,在docker文件夹下新建一个Dockerfile文件,写入一下内容:

FROM java:8u111
VOLUME /tmp
ADD *.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
# Ubuntu 时区
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

上面两步的作用,就是在项目根目录的docker文件夹下,创建了一个Dockerfile,并且maven打包的时候会把对应的jar包复制到这个目录下。

3.6. idea,配置docker

我们打开settings可以看到docker

点击+,添加一个连接。上图已经添加好了,如果有2台vm可以添加两个,比如我的是Docker66和Docker129,分别对应2个vm带上的docker服务。

然后配置docker启动项
选择编辑:

添加一个启动项:

填写docker相关的参数:

3.7. idea,运行,在目标机器构建容器

直接运行就是了,可以看到开始构建了(上一步配置docker的时候,server选到“Docker129”,代表目标容器要在129上)

去129上看一下,docker ps

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                    NAMES
8f032e353cd8        d16121b844eb        "java -jar /app.jar"   2 hours ago         Up 2 hours          0.0.0.0:8761->8761/tcp   eureka-server

至此,就可以在本地idea改代码,直接点击debug,就可以重新生成镜像并启动容器~

4. 在两个vm docker上部署sc集群

目标:在vm1中部署注册中心eureka,在vm2中部署service-provider

4.1. docker网络知识

由于我们是想在vm1里面部署eureka-server,在vm2里面部署service-provider,那么问题来了,service-provider是否可以注册到eureka-server?通过什么ip注册?更进一步,当我们再启动service-consumer之后,service-consumer用什么调用service-provider?

  • 这里就是需要我们把两个vm连接起来,这种连接的方式,简单的说就是构建一个swarm集群,集群内,可以建立overlay网络。

  • swarm网络需要选择一个vm做manager,比如我选择的是vm1,在上面执行创建swarm集群的命令,并得到加入swarm网络的命令

  • 将上一步得到的“加入swarm网络的命令”,在vm2上执行,那么vm2就加到swarm网络了,这样vm1和vm2组成了一个集群

  • overlay网络是在swarm集群的基础上创建出来的虚拟网络,可以有自己的网段、网关等。

  • 我们在swarm manager节点(vm1)执行创建overlay网络的命令,那么vm2上通过docker network ls是可以看到在vm1上创建的overlay网络的。

创建swarm集群,参考:https://blog.csdn.net/wangxw1803/article/details/90782463 下面也会一步步创建swarm和overlay

4.2. 避坑命令 - 开docker端口

为了下面的操作不踩坑,建议先在2个vm上执行下面的开启防火墙端口的命令

firewall-cmd --zone=public --add-port=7946/tcp --permanent
firewall-cmd --zone=public --add-port=7946/udp --permanent
firewall-cmd --zone=public --add-port=4789/udp --permanent
firewall-cmd --zone=public --add-port=4789/tcp --permanent
firewall-cmd --zone=public --add-port=2375/tcp --permanent
firewall-cmd --zone=public --add-port=2375/udp --permanent
firewall-cmd --zone=public --add-port=2377/udp --permanent
firewall-cmd --zone=public --add-port=2377/tcp --permanent
firewall-cmd --reload

4.3. 创建swarm集群

创建swarm集群,参考:https://www.cnblogs.com/xiangsikai/p/9938374.html

我们选择vm1位manager节点,在manager节点上执行

docker swarm init --advertise-addr 172.18.100.129

可以得到一串加入此swarm集群的命令。

在worker节点上执行上述操作获得命令。

docker swarm join --token SWMTKN-1-3emp34nuyoo2imoeh0z4n3ukgpa62l31qlmf9d2r27lol24rr9-1me1d6hjif1f3695l2ioi46ir 172.18.100.129:2377

在manager节点上查看swarm节点情况

[root@localhost ~]# docker node ls
ID                            HOSTNAME                STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
dbqfnbvywasa6gl4s1nr1q921     localhost.localdomain   Ready               Active                                  19.03.5
mg5zdsuqeuo9bvh4z2q2i6tpg *   localhost.localdomain   Ready               Active              Leader              19.03.1

至此,swarm集群就创建好了,非常简单。

4.4. 创建overlay网络

大白话,overlay网络要解决的问题就是,分布在两个vm里的docker容器,怎么样可以相互访问。

举个栗子:

在vm1里docker容器ip是10.0.1.5,在vm2里docker容器ip是10.0.1.6。但是vm1的ip是172.18.100.129,vm2是172.18.100.66,如果我们从10.0.1.5这个容器里直接ping 10.0.1.6,是不通的,怎么样才可以访问?那就是建立overlay网络。

创建overlay网络,参考:https://www.cnblogs.com/xiangsikai/p/9938374.html

具体创建overlay网络操作命令如下:

  • 在swarm manager节点,执行创建命令

    docker network create -d overlay --attachable my-network2
    
  • 在vm2上,执行docker network ls,可以看到my-network2网络

    [root@localhost ~]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    1f722f207cac        bridge              bridge              local
    3aadcb52b3df        docker_gwbridge     bridge              local
    3744ee928016        host                host                local
    587fwg44wbnk        ingress             overlay             swarm
    sqi2konhybf9        my-network2         overlay             swarm
    a184e66697b0        none                null                local
    

至此,overlay网络也构建好了。可以通过idea来构建服务看看eureka-server和service-provider的连通性。见下面内容。

4.5. 部署sc服务

有一个系列文章写的还行,比较简洁,当比较熟练的就直接照抄:https://my.oschina.net/mdxlcj/blog/2995192

4.5.1. 部署eureka-server

要验证eureka-server和service-provider的连通性,其实就是在idea里面的docker运行配置里,加上–network=my-network2这个运行配置加上即可,如下:

确认eureka-server使用了my-network2这个overlay网络,可以执行命令

docker network inspect my-network2

可以看到eureka-server是加入了overlay网络,并且其ip地址是10.0.1.13,如下图。那么后面一步要做的,就是把service-provider部署在vm2,也加入my-network2这个overlay网络,其注册中心地址就是10.0.1.13,如果可以注册上,那代表两个容器是互通了。

4.5.2. 部署service-provider

注意:eureka-client的pom中要加web模块,否则启动之后会直接退出unregistered

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

4.5.3. 确认vm2 docker中的service-provider是否可以注册到vm1 docker中的eureka-server

4.5.4. 考虑在vm1上部署一个service-consumer

在vm1上部署一个service-consumer,注册中eureka-server,并调用service-provider的接口

  • 创建一个springboot的service-consumer工程

    具体service-consumer代码上的改造,参考:https://my.oschina.net/mdxlcj/blog/3139142

    同样构建好容器,并加入my-network2网络,通过 docker network inspect my-network2查看此网络上的容器及ip

此时从10.0.1.12 ping 10.0.1.10不通,怀疑是昨天重启vm后,119机器的ip变到了223,所以重新建swarm和overlay再试一下。(剧透一下ping不同的确跟vm ip漂移有关,重建swarm和overlay网络之后就可以了)

这里有个小插曲:在建立swarm集群后,新建的overlay网络可能没那么快在vm2上显示出来,就是说在vm2上执行docker network ls看不到my-network2网络,为了确定情况,可以执行下面的命令来尝试网络是否OK

docker service create --replicas 1 --name mytest --network my-network2 --constraint 'node.hostname == vm2' alpine ping baidu.com
  • 把service-provider的注册中心改到docker ip,看是否可以注册上

结果可以注册上,并且调用http://172.18.100.223:8076/test1也是可以看到页面输出Hello world!

此时,service-provider和service-consumer注册的eureka地址都是其docker容器的内部ip,为10.0.0.5,从service-consumer调用service-provider是OK的。

  • 再尝试一下把service-provider和service-consumer使用eureka的虚拟机ip来注册,看是否可以,即把eureka-server的地址改到。这么做的意义是生产上可以在应用里只指定eureka的地址,其他的服务,都是通过docker ip相互调用,不需要指定确定ip
eureka.client.serviceUrl.defaultZone=http://172.18.100.223:8761/eureka/

注册没有问题的,相互调用也是OK的

4.6. 部署sc服务结论,swarm与overlay

  • 各vm情况:

vm1: 171.18.100.223。其上docker:eureka-server(10.0.0.5),eureka-consumer(10.0.0.10)

vm2:172.18.100.66。其上docker:service-provider(10.0.0.9)

  • sc配置:

eureka-server不需要配置ip

service-provider的注册中心,可以是vm1的171.18.100.223,也可以是docker的10.0.0.5

service-consumer的注册中心,可以是vm1的171.18.100.223,也可以是docker的10.0.0.5

访问service-consumer,http://172.18.100.223:8076/test1,都可以拿到结果

  • 创建swarm集群命令

    docker swarm init --advertise-addr 172.18.100.223

    172.18.100.223是vm的ip,要注意修改,然后获取类似下面的命令,在swarm work节点上去执行

    docker swarm join --token SWMTKN-1-51p9uylvwzfzwt7qqu9e1mlcfyt60py8icg1tvoqtm5pz6f0nh-e1lkiunldyrt7o0eany0sa4yx 172.18.100.223:2377

  • 创建overlay网络

    docker network create -d overlay --attachable my-network2

    –attachable比较重要,不然容器可能加入不了网络

    在manager节点创建overlay网络后,可能没有那么快同步到work节点上,就是说在work节点上执行docker network ls看不到my-network2,可以通过执行下面的命令,再次确认网络是否建好了

    docker service create --replicas 1 --name mytest --network my-network2 --constraint 'node.hostname == vm2' alpine ping baidu.com
    
  • 避坑命令,最好在vm上都执行一遍

    firewall-cmd --zone=public --add-port=7946/tcp --permanent
    firewall-cmd --zone=public --add-port=7946/udp --permanent
    firewall-cmd --zone=public --add-port=4789/udp --permanent
    firewall-cmd --zone=public --add-port=4789/tcp --permanent
    firewall-cmd --zone=public --add-port=2375/tcp --permanent
    firewall-cmd --zone=public --add-port=2375/udp --permanent
    firewall-cmd --zone=public --add-port=2377/udp --permanent
    firewall-cmd --zone=public --add-port=2377/tcp --permanent
    firewall-cmd --reload
    
  相关解决方案