文章目录
Docker Compose快速人门
Docker-Compose是Docker的一种编排服务,是一个用于在Docker上定义并运行复杂应用的工具,可以让用户在集群中部署分布式应用。
通过Docker-Compose用户可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose解决了容器与容器之间如何管理编排的问题。
使用Compose大致有3个步骤:
- 使用Dockerfile(或其他方式)定义应用程序环境,以便在任何地方重现该环境。
- 在docker-compose.yml文件中定义组成应用程序的服务,以便各个服务在一个隔离的环境中一起运行。
- 运行docker-compose up命令,启动并运行整个应用程序。
入门示例
下面以cloud-eureka 为例讲解Compose的基本步骤。
- 使用mvn clean package命令打包项目,获得 jar 包cloud-eureka-1.0.jar。
- 在cloud-eureka-1.0.jar所在路径(默认是项目的target目录)创建Dockerfile文件,并在其中添加如下内容。
FROM java:8
VOLUME /tmp
ADD cloud-eureka-1.0.jar app.jar
RUN bash -c 'touch /app.jar'
EXPOSE 8888
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
- 在cloud-eureka-1.0.jar所在路径创建文件docker-compose.yml,在其中添加如下内容
version: '2' #表示该docker-compose.yml文件使用的是Version 2 file format
services:
cloud-eureka: #指定服务名称
build: . #指定Dockerfile所在路径
ports:
- "8888:8888" #指定端口映射,类似docker run的-p选项,注意使用字符串形式
- 在docker-compose.yml所在路径执行以下命令
docker-compose up
C:\Users\c\Desktop\spring-cloud-demo\cloud-eureka\target>docker-compose up
Building cloud-eureka
Step 1/6 : FROM java:8
---> d23bdf5b1b1b
Step 2/6 : VOLUME /tmp
---> Running in dd4c4cd3ed21
Removing intermediate container dd4c4cd3ed21
---> 5958683417bd
Step 3/6 : ADD cloud-eureka-1.0.jar app.jar
---> 6d5eeb172ef0
Step 4/6 : RUN bash -c 'touch /app.jar'
---> Running in 83fb6d9236a3
Removing intermediate container 83fb6d9236a3
---> 951cf2bc0e3c
Step 5/6 : EXPOSE 8888
---> Running in 0f5e1c0e51d9
Removing intermediate container 0f5e1c0e51d9
---> f239f83036c3
Step 6/6 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
---> Running in fdf1f5ca9c1c
Removing intermediate container fdf1f5ca9c1c
---> 0b1191090ef1
Successfully built 0b1191090ef1
Successfully tagged target_cloud-eureka:latest
WARNING: Image for service cloud-eureka was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --bu
ild`.
Creating target_cloud-eureka_1 ... done
Attaching to target_cloud-eureka_1
cloud-eureka_1 | 2019-10-21 12:28:14.223 INFO 1 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.Configu
rationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$412
c03e1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
cloud-eureka_1 |
cloud-eureka_1 | . ____ _ __ _ _
cloud-eureka_1 | /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
cloud-eureka_1 | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
cloud-eureka_1 | \\/ ___)| |_)| | | | | || (_| | ) ) ) )
cloud-eureka_1 | ' |____| .__|_| |_|_| |_\__, | / / / /
cloud-eureka_1 | =========|_|==============|___/=/_/_/_/
cloud-eureka_1 | :: Spring Boot :: (v2.1.1.RELEASE)
cloud-eureka_1 |
cloud-eureka_1 | 2019-10-21 12:28:15.149 INFO 1 --- [ main] com.cc.cloud.eureka.EurekaApp : No active profile set, falling back to default profil
es: default
cloud-eureka_1 | 2019-10-21 12:28:18.531 WARN 1 --- [ main] o.s.boot.actuate.endpoint.EndpointId : Endpoint ID 'service-registry' contains invalid chara
cters, please migrate to a valid format.
cloud-eureka_1 | 2019-10-21 12:28:19.746 INFO 1 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=18263b77-2811-368f-bf5d-788d928dd71a
cloud-eureka_1 | 2019-10-21 12:28:20.197 INFO 1 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.Configu
rationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$412
c03e1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
cloud-eureka_1 | 2019-10-21 12:28:21.636 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8888 (http)
cloud-eureka_1 | 2019-10-21 12:28:21.798 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
cloud-eureka_1 | 2019-10-21 12:28:21.803 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/9.0.13
执行完命令之后,Compose就会自动构建镜像并使用镜像启动容器。也可使用docker-compose up -d
后台启动并运行这些容器。
我们通过docker images
可以看到,我们会产生一个target_cloud-eureka
的镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
target_cloud-eureka latest 0b1191090ef1 46 minutes ago 731MB
- 访问
http://宿主机IP:8888/
,即访问http://192.168.99.100:8888/,即可访问到Eureka Server首页。
使用Docker Comose编排Spring Cloud微服务
接下来我们需要把我们的微服务通过Docker Comose去编排。
使用Maven插件读取Dockerfile进行构建
我们首先介绍使用Maven插件读取Dockerfile进行构建。
- maven插件的配置如下
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>cloud-demo/${project.artifactId}:${project.version}</imageName>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
- 我们需要在我们
${project.basedir}/src/main/docker
目录下都创建Dockerfile
内容基本如下一致:
FROM java:8
VOLUME /tmp
ADD cloud-service-member-1.0.jar app.jar
RUN bash -c 'touch /app.jar'
EXPOSE 8762
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
- 编写docker-compose.yml文件
version: '3'
services:
rabbitmq:
image: rabbitmq:management
hostname: rabbitmq
ports:
- "15672:15672"
- "5672:5672"
restart: always
cloud-eureka:
image: cloud-demo/cloud-eureka:1.0
hostname: cloud-eureka
ports:
- "8888:8888"
restart: always
cloud-config-server:
image: cloud-demo/cloud-config-server:1.0
hostname: cloud-config-server
ports:
- "8090:8090"
links:
- cloud-eureka
- rabbitmq
depends_on:
- cloud-eureka
- rabbitmq
restart: always
cloud-zuul:
image: cloud-demo/cloud-zuul:1.0
hostname: cloud-zuul
links:
- cloud-eureka
- rabbitmq
- cloud-zipkin
ports:
- "8769:8769"
depends_on:
- cloud-eureka
- rabbitmq
- cloud-config-server
- cloud-zipkin
restart: always
cloud-service-member:
image: cloud-demo/cloud-service-member:1.0
links:
- cloud-eureka
- rabbitmq
- cloud-zipkin
hostname: cloud-service-member
ports:
- "8762:8762"
depends_on:
- cloud-eureka
- rabbitmq
- cloud-config-server
- cloud-zipkin
restart: always
cloud-service-order:
image: cloud-demo/cloud-service-order:1.0
links:
- cloud-eureka
- rabbitmq
- cloud-zipkin
hostname: cloud-service-order
ports:
- "8765:8765"
depends_on:
- cloud-eureka
- rabbitmq
- cloud-config-server
- cloud-zipkin
restart: always
cloud-admin-server:
image: cloud-demo/admin-server:1.0
links:
- cloud-eureka
hostname: cloud-admin-server
ports:
- "8098:8098"
depends_on:
- cloud-eureka
restart: always
cloud-hystrix-dashboard:
image: cloud-demo/cloud-hystrix-dashboard:1.0
hostname: cloud-hystrix-dashboard
ports:
- "8766:8766"
restart: always
cloud-turbine:
image: cloud-demo/cloud-turbine:1.0
hostname: cloud-turbine
ports:
- "6100:6100"
links:
- cloud-eureka
depends_on:
- cloud-eureka
restart: always
cloud-zipkin:
image: cloud-demo/cloud-zipkin:1.0
hostname: cloud-zipkin
ports:
- "9411:9411"
restart: always
这里介绍一下为什么需要配置restart: always
。
docker-compose可以方便组合多个 docker 容器服务, 但是, 当容器服务之间存在依赖关系时, docker-compose 并不能保证服务的启动顺序。docker-compose 中的 depends_on 配置是容器的启动顺序, 并不是容器中服务的启动顺序。
也就是说容器的就绪顺序是不能保证的,也就是不能保证先把一个服务启动完毕之后再启动另一个服务。比如我们的config client需要连接config server,但是可以config server还没完全启动完毕,config client已经在启动了,并且config server还没有就绪,所以导致config client端连接失败,导致启动失败。
所以我暂时的解决方法是使用足够的容错和重试机制,比如从配置中心获取配置文件,服务消费者可以不断的重试直到连上为止,这里就用到了docker-compose 中的restart配置
- 修改连接的IP地址
默认情况下,Compose会为应用创建一个网络,服务的每个容器都会加入该网络中。
这样,容器就可被该网络中的其他容器访问,不仅如此,该容器还能以服务名称作为hostname被其他容器访问。
所以我们需要把之前用IP地址的配置都改成服务名,比如:
eureka:
client:
serviceUrl:
defaultZone: http://cloud-eureka:8888/eureka/
还有如下:
spring:
zipkin:
enabled: true
base-url: http://cloud-zipkin:9411
sender:
type: web
sleuth:
sampler:
#收集追踪信息的比率,如果是0.1则表示只记录10%的追踪数据,如果要全部追踪,设置为1(实际场景不推荐,因为会造成不小的性能消耗)
probability: 1
rabbitmq:
host: rabbitmq
port: 5672
username: guest
password: guest
- 构建镜像
执行如下命令:
mvn clean install -pl cloud-eureka,cloud-config-server,cloud-zipkin,admin-server,cloud-zuul,cloud-hystrix-dashboard,cloud-turbine,cloud-service-member,cloud-service-order docker:build
我直接使用mvn clean install docker:build
好像会把parent目录都构建了,所以失败了,所以我这里只能指定需要构建的子模块。
执行完毕之后就可以使用docker images
查看,可以看到我们的镜像都构建出来了。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cloud-demo/cloud-config-server 1.0 237c8f8e725d 15 minutes ago 746MB
cloud-demo/admin-server 1.0 dde41e011b46 16 minutes ago 743MB
cloud-demo/cloud-zipkin 1.0 71246b3ccc2b 16 minutes ago 685MB
cloud-demo/cloud-zuul 1.0 680a2ae0246b 16 minutes ago 739MB
cloud-demo/cloud-turbine 1.0 c440eb63223c 16 minutes ago 728MB
cloud-demo/cloud-hystrix-dashboard 1.0 9be879668dc6 16 minutes ago 709MB
cloud-demo/cloud-service-order 1.0 c39a9362da20 16 minutes ago 742MB
cloud-demo/cloud-service-member 1.0 54750b8f66e9 16 minutes ago 742MB
cloud-demo/cloud-eureka 1.0 d1d25421ff11 16 minutes ago 731MB
rabbitmq management 4b23cfb64730 4 days ago 180MB
java 8 d23bdf5b1b1b 2 years ago 643MB
- 执行
docker-compose up
命令
可以使用docker ps
进行查看,可以看到我们的服务都启动起来了。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec8799529e40 cloud-demo/cloud-service-order:1.0 "java -Djava.securit…" 15 minutes ago Up 13 minutes 0.0.0.0:8765->8765/tcp spring-cloud-demo_ cloud-service-order_1
0861fb0178e3 cloud-demo/cloud-service-member:1.0 "java -Djava.securit…" 15 minutes ago Up 13 minutes 0.0.0.0:8762->8762/tcp spring-cloud-demo_ cloud-service-member_1
88e7b4c1548f cloud-demo/cloud-zuul:1.0 "java -Djava.securit…" 15 minutes ago Up 13 minutes 0.0.0.0:8769->8769/tcp spring-cloud-demo_ cloud-zuul_1
bb8021f768b5 cloud-demo/cloud-config-server:1.0 "java -Djava.securit…" 15 minutes ago Up 15 minutes 0.0.0.0:8090->8090/tcp spring-cloud-demo_ cloud-config-server_1
534de73c2550 cloud-demo/cloud-turbine:1.0 "java -Djava.securit…" 15 minutes ago Up 15 minutes 0.0.0.0:6100->6100/tcp spring-cloud-demo_ cloud-turbine_1
2a741813c006 cloud-demo/admin-server:1.0 "java -Djava.securit…" 15 minutes ago Up 15 minutes 0.0.0.0:8098->8098/tcp spring-cloud-demo_ cloud-admin-server_1
5e509ee8e669 rabbitmq:management "docker-entrypoint.s…" 15 minutes ago Up 15 minutes 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp spring-cloud-demo_ rabbitmq_1
c5622fac19bc cloud-demo/cloud-zipkin:1.0 "java -Djava.securit…" 15 minutes ago Up 15 minutes 0.0.0.0:9411->9411/tcp spring-cloud-demo_ cloud-zipkin_1
5d09ecb673e7 cloud-demo/cloud-eureka:1.0 "java -Djava.securit…" 15 minutes ago Up 15 minutes 0.0.0.0:8888->8888/tcp spring-cloud-demo_ cloud-eureka_1
1bd620439bab cloud-demo/cloud-hystrix-dashboard:1.0 "java -Djava.securit…" 15 minutes ago Up 15 minutes 0.0.0.0:8766->8766/tcp spring-cloud-demo_ cloud-hystrix-dashboard_1
- 测试
- 查看eureka
- 查看rabbitmq
- 查看Admin Server Console
- 分别访问我们的order还有member服务。
- 查看zipkin
- 查看Turbine
- 测试refresh config server配置
这里可能会遇到一个问题,就是如果你的docker虚机设置的内存和CPU的配置如果太低的话,当启动多个容器的时候,可能会导致服务挂掉。所以先把docker的配置调高一点。可以通过docker info
命令查看到配置信息。
还有就是在构建镜像的过程中如果报了如下的错误:
[ERROR] Failed to execute goal com.spotify:docker-maven-plugin:0.4.13:build (default-cli) on project cloud-eureka: Exception caught: Get https://registry-1.docker.io/v2
/: net/http: TLS handshake timeout -> [Help 1]
[ERROR]
原因是我们的镜像拉不下来,这个时候我们就需要去修改一下我们docker的拉取镜像地址,最好改成国内的镜像源,比如阿里云的镜像加速器地址。
我们可以使用docker info
命令查看当前的镜像源地址
接下来我们介绍怎么修改我们的镜像源地址
- 首先使用如下命令进入docker machine
docker-machine ssh default
- 执行如下命令修改
sudo sed -i "s|EXTRA_ARGS='|EXTRA_ARGS='--registry-mirror=这里是你的镜像加速地址 |g" /var/lib/boot2docker/profile
- 然后使用
exit
命令退出docker machine - 最后使用
docker-machine restart default
命令重启docker machine - 使用
docker info
查看信息
源码:https://gitee.com/cckevincyh/spring-cloud-demo/tree/release-docker-compose-dockerfile
使用Maven插件构建Docker镜像
其实跟之前都是类似的,只是我们不需要使用Dokcerfile去构建镜像了,我们只需要修改maven插件的配置即可。
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<forceTags>true</forceTags>
<imageName>cloud-demo/${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>
然后执行如下命令就可以构建镜像了。
mvn clean install -pl cloud-eureka,cloud-config-server,cloud-zipkin,admin-server,cloud-zuul,cloud-hystrix-dashboard,cloud-turbine,cloud-service-member,cloud-service-order docker:build
然后最后就是执行docker-compose up
命令。
源码:https://gitee.com/cckevincyh/spring-cloud-demo/tree/release-docker-compose/
参考
SpringCloud与Docker微服务架构实战-完整版.pdf
Docker | 第七章:Docker Compose服务编排介绍及使用
如何写docker-compose.yml,Docker compose file 参考文档
Maven多模块项目单独编译子模块项目时报错:Failed to execute goal on project/Could not resolve dependencies for project
解决 docker: Error response from daemon: … : net/http: TLS handshake timeout.
源代码
https://gitee.com/cckevincyh/spring-cloud-demo/tree/release-docker-compose-dockerfile
https://gitee.com/cckevincyh/spring-cloud-demo/tree/release-docker-compose/