1. 前言
上一篇文章中讲了服务注册中心eureka-server、服务消费者service-a、服务提供者service-b,service-a和service-b在服务注册中心中进行服务注册之后,service-a成功调用service-b的服务,整个应用比较简单,没有太多的难点,而spring cloud应用打进docker中运行也是十分简单的,因此这次再次尝试了下将三个服务都使用docker运行起来,之前两次也试过编写dockerfile文件,然后打成镜像,运行容器,但是当时的方法一直是将整个源码都打入到镜像中,然后运行容器的时候,需要去官网下载jar包,应用编译打包才能运行起来,太过耗时,因此这次经过多次尝试以后,成功将打包出来的jar文件打进镜像中,打包镜像、启动容器都十分简单快捷,无需那么多的操作,这次就把这些过程完全的讲述一遍。
2. 目录结构
如上次一般,这次依然是要展示一下当前工程的目录结构,在上个应用的基础上,就只是增加了几个模块的Dockerfile文件和docker-compose.yml文件和一个用来打出镜像的bash脚本,整体目录如下:
.
├── build.gradle├── buildDockerImage.sh├── docker-compose.yml├── eureka-server
│ ├── Dockerfile
│ ├── build.gradle│ └── src
│ └── main
│ ├── java
│ │ └── cn
│ │ └── com│ │ └── enreka
│ │ └── EurekaServerApplication.java│ └── resources
│ └── bootstrap.yml├── gradlew
├── gradlew.bat├── service-a
│ ├── Dockerfile
│ ├── build.gradle│ └── src
│ └── main
│ ├── java
│ │ └── cn
│ │ └── com│ │ └── devh
│ │ ├── A1ServiceApplication.java│ │ ├── controllers
│ │ │ └── AServiceController.java│ │ └── fegin
│ │ └── ServiceBClient.java│ └── resources
│ ├── application.yml│ └── bootstrap.yml├── service-b
│ ├── Dockerfile
│ ├── build.gradle│ └── src
│ └── main
│ ├── java
│ │ └── cn
│ │ └── com│ │ └── devh
│ │ ├── B1ServiceApplication.java│ │ └── controllers
│ │ └── ServiceB1Controller.java│ └── resources
│ ├── application.yml│ └── bootstrap.yml├── settings.gradle└── zuul
├── build.gradle
└── src
└── main
├── java
│ └── cn
│ └── com
│ └── zuul
│ └── ZuulApplication.java
└── resources12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
每个模块的Dockerfile文件都在该模块的根目录下面,便于在执行这个Dockerfile文件时方便找到build中的jar包,buildDockerImage.sh脚本用于执行脚本对每个模块中的Dockerfile文件执行然后打出镜像。
docker-compose.yml放在根目录下,便于在所有镜像都完成后直接根据镜像启动容器运行。
3. 配置文件的修改
如果使用docker来运行的话,配置文件也要做一定程度的修改,具体如下:
eureka-server 中的bootstrap.yml:
增加配置:
---spring:
profiles: docker
application:
name: eureka-serverserver:
port: 8761eureka:
instance:
hostname: eureka-server
prefer-ip-address: true
lease-expiration-duration-in-seconds: 30
lease-renewal-interval-in-seconds: 30
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://eureka-server:8761/eureka/
server:
enable-self-preservation: false12345678910111213141516171819202122
service-a中的bootstrap.yml,
增加配置:
---spring:
profiles: docker
application:
name: service-aserver:
port: 8080eureka:
instance:
hostname: service-a
prefer-ip-address: true
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://eureka-server:8761/eureka/123456789101112131415161718
service-b中的bootstrap.yml:
增加配置:
---spring:
profiles: docker
application:
name: service-bserver:
port: 8070eureka:
instance:
hostname: service-b
prefer-ip-address: true
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://eureka-server:8761/eureka/123456789101112131415161718
以上就是每一个一个配置选项,以这个环境运行后,就是docker容器之间进行通讯。
4. Dockerfile文件
–
除去以上给每个服务新的配置以外,我们还需要将三个服务打到镜像中的Dockerfile脚本,具体如下:
4.1 eureka server Dockerfile文件
FROM java:8RUN mkdir /app
WORKDIR /app
COPY build/libs/eureka-server.jar /app
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/eureka-server.jar", "--spring.profiles.active=docker"]
EXPOSE 87611234567
Dockerfile中的指令不做描述,不明白的可以找一篇基础文章看看,以前编写Dockerfile的时候,都是将整个应用的源码全部copy到基础镜像之中,这样造成的问题就是运行容器的时候需要相当长的时间去下载依赖和编译jar,但是直接将已经编译打包好的jar copy到容器中是最为方便的,之前也是这样尝试过,但是一直是失败的,可能原因是选择的目录不正确的原因。
4.2 service-a、service-b Dockerfile文件
service-a和service-b的Dockerfile文件类似,如下:
service-a:
FROM java:8RUN mkdir /app
WORKDIR /app
COPY build/libs/service-a.jar /app
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/service-a.jar", "--spring.profiles.active=docker"]
EXPOSE 80801234567
service-b:
FROM java:8RUN mkdir /app
WORKDIR /app
COPY build/libs/service-b.jar /app
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/service-b.jar", "--spring.profiles.active=docker"]
EXPOSE 80701234567
对外暴露的端口分别是8080和8070,同时都指定了运行的profile为docker,即我们新编写的配置文件。
5. bash脚本
bash脚本的用途是分别执行几个module下的Dockerfile文件,分别打成镜像,不用一个个手工执行,文件如下:
buildDockerImage.sh:
#!/usr/bin/env bashset -eo pipefail
modules=( eureka-server service-a service-b )for module in "${modules[@]}"; do
docker build -t "microservice/${module}:latest" ${module}done123456789
使用十分简单,就是使用docker build分别执行每个模块下的Dockerfile文件,然后简便起见,直接就是最新的版本,其实按照规范一点,最好是每次打出的镜像的版本号都是依次递增的,这样回退是十分方便的。
6. docker-compose.yml文件
最后就是docker-compose.yml文件,这个脚本中的内容是一次性启动这几个服务,并实现服务之间的通信,脚本内容如下:
docker-compose.yml:
eureka-server:
image: microservice/eureka-server
hostname: eureka-server
ports:
- "8761:8761"service-b:
image: microservice/service-b
ports:
- "8070:8070" links:
- "eureka-server"service-a:
image: microservice/service-a
ports:
- "8080:8080" links:
- "eureka-server" - "service-b"1234567891011121314151617181920
三个服务,使用的image都是先前打出的镜像,然后容器内的端口映射物理机上的端口,最后是通信的模块,这因此也是先前的配置文件之中不再是指定的ip,而是服务名, 这里就可以通过服务名来找到对应的服务。
7. 编译与运行
我们执行脚本buildDockerImage.sh,控制台输出如下:
如此几步新的镜像就已经成功打成功了,可以执行命令docker images查看镜像,如下:
这就是成功打出的三个镜像,现在根据这三个镜像运行对应的容器即可,在工程目录下,执行命令docker-compose up -d启动容器并运行,并执行docker ps查看运行起来的容器,如下图:
三个服务已经成功启动,现在访问http://192.168.99.100:8761/,这是先前docker配置的本地的ip192.168.99.100,8761对应的服务为eureka,访问如下:
两个服务已经注册成功,访问对应的service-a提供的服务http://192.168.99.100:8080/,得到如下结果:
与上文相同,三个服务在docker容器中运行正常,相互之间通信也正常。
本文出自http://blog.csdn.net/u012734441/article/details/77832797