1.环境
vmware 10 workstation centos 7 docker docker compose
前提条件 idea 中 docker ingegration安装
项目结构为父子结构,父项目的pom配置docker 部分
<!-- docker管理-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.11</version>
<configuration>
<dockerHost>http://${host.machine}:2375</dockerHost>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<imageName>gaxh/${project.artifactId}</imageName>
<forceTags>true</forceTags>
<imageTags>
<imageTag>v0.0.1</imageTag>
</imageTags>
<skipDockerBuild>true</skipDockerBuild>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<skipDockerBuild>true</skipDockerBuild>的意义是
因为父项目pom中maven-antrun插件
<!-- 构建docker文件信息 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy todir="${project.basedir}/src/main/docker" overwrite="true" preservelastmodified="true">
<fileset dir="${root-dir}">
<include name="Dockerfile"/>
</fileset>
<fileset dir="${root-dirp}">
<include name="Dockerfile"/>
</fileset>
</copy>
<replace file="${project.basedir}/src/main/docker/Dockerfile" token="#@docker-final-jar#" value="${project.build.finalName}"/>
<!-- 读取属性文件 -->
<property file="${project.basedir}/src/main/resources/bootstrap.properties"/>
<replace file="${project.basedir}/src/main/docker/Dockerfile" token="#@docker-final-port#" value="${server.port}"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
在执行maven clean package -Dmaven.test.skip=true时候会自动生成子项目dockerfile文件,不用手动各个去写。
生成dockerfile以后,在子项目的pom中添加一下配置覆盖掉父项目的<skipDockerBuild>true</skipDockerBuild>如图
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration><skipDockerBuild>false</skipDockerBuild></configuration>
</plugin>
这样在idea的项目根目录下teminal中执行mvn clean package docker:build -DskipTests 时各个子模块会自动生成image并上传到docker,批量执行提高效率,当然也可以在单个的子模块中操作。
并配置环境变量
2. 微服务项目
a.springg eureka
bootstrap.peroperties配置:
spring.application.name=eureka-server
server.port=7880
#eureka.instance.hostname=localhost
eureka.server.enable-self-preservation: false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:${server.port}/eureka/
eureka.instance.prefer-ip-address=true
dockerfile 内容
FROM java:8
VOLUME /tmp
ADD eureka-sever-0.0.1-SNAPSHOT.jar /app.jar
RUN bash -c 'touch /app.jar'
RUN echo "Asia/shanghai" > /etc/timezone
EXPOSE 7880
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
执行maven package
生成jar包,再执行
会生成镜像文件,并上传到虚拟机。这是单个项目的生成方式。
b.config server的配置
docker 配置参考类似eureka,application.yml配置如图
server:
port: 7881
eureka:
instance:
hostname: config-server
prefer-ip-address: true
client:
registerWithEureka: true
fetchRegistry: false
serviceUrl:
defaultZone: http://192.168.121.128:7880/eureka/
healthcheck: true
#SVN配置
spring:
application:
name: config-server
cloud:
config:
server:
git:
username: 自己定义
password: 自己定义
uri: https://github.com/niufwshd/config-repo
discovery:
enabled: true
enabled: true
config-server构建以后会注册到eureka,并配置git为配置文件存储地址。
c. 配置中心客户端项目
主要看下配置文件
eureka:
instance:
prefer-ip-address: true
client:
serviceUrl:
defaultZone: http://192.168.121.128:7880/eureka
spring:
application:
name: config-client
cloud:
config:
name: config-client #对应config server Url中的{application}
profile: dev #配置环境,对应config server Url中的{profile}
#label: trunk #配置分支(不配置则默认:git则是master,svn则是trunk),
#uri: http://192.168.121.128:7881 #配置中心地址
discovery:
enabled: true
service-id: config-server
management:
security:
enabled: false
basic:
enabled: false
客户端获取配置的方式有两种
(1)、通过uri,如
#uri: http://192.168.121.128:7881 #配置中心地址
这种方式可以避开docker container 不能相互连通访问的问题,很方便,但地址是硬编码的。
(2)、通过service discovery
客户端也会注册到eureka并且通过server-id自动发现配置中心,来获取配置比较智能。但是一个很头大的问题是
当三个项目都部署到docker中时候,eureka里显示的是容器的id,地址一般都是172.17.*.*.这样客户端一般是访问不到config server的,因此不能获取配置,所以通过docker compose编排来解决。
在客户端的根目录创建docker-compose.yml
内容为
version: "3"
services:
eureka-server:
image: sha256:2da935cf36a5d0127db6be994f10d40a6aac0ad80d9c1d855622a4ba9a02632e
hostname: eurekaserver
ports:
- "192.168.121.128:7880:7880"
config-server:
image: sha256:da2d0a7d5f64c7c30f939dc0c9c3dfee9c6839fbb778947de35def7a13fe6315
hostname: configserver
ports:
- "192.168.121.128:7881:7881"
depends_on:
- eureka-server
restart: always
config-client:
image: sha256:b892f9e827402c6517fe7663bdbe3ddbdc487e149e1dbca2d9f90083717b31c3
hostname: configclient
ports:
- "192.168.121.128:8008:8008"
depends_on:
- eureka-server
- config-server
restart: always
通过docker composedocker文档知道docker compose编排的容器可以相互访问,所以可以自动发现配置(我的电脑比较慢,另外和container执行也比较慢).,对上面的compose.yml稍作说明,我使用的是image的id,因为image都已经上传到了虚拟机。
可以从ide的docker插件的属性中拷贝如图
hostname不知道有没有用,port做了端口映射,并设置了虚拟机的ip地址,方便外部访问。关键之处是通过dependson定义了容器的启动顺序,单不能保证image的运行顺序就是这样。所以最好在浏览器中输入网址确认,顺序是eureka ---》config server----》config-client。如图
我的配置里只定义了一个server.port,在客户端的controller进行访问
这里通过@value注解的简单访问,打开浏览器输入客户端的地址看效果
至此通过docker部署微服务自动发现配置的方式已经完成,uri的方式不用docker compose也可以。第一次写博客,希望大家多提意见和建议。