写在前面
最近在工作中需要使用到apollo配置中心来简化微服务开发,在部署时使用docker的方式部署到线上到docker swarm集群。在网上翻了很多人的博文,有些由于时间久远很多东西都发生来变化,而有些对一些坑的细节没有做详细说明,最后还是我在官方文档中扒到了解决方法。
因此在踩完了所有坑后,详细的记录一便流程,方便大家有相同的需求时可以按图索骥,也作为备忘录方便以后回顾。
一、准备工作
1.1 docker环境安装
由于针对生产环境部署情景,需要在本地环境及服务器都准备好docker环境,如果只是本机玩玩的话,只需准备本地docker环境。至于docker的安装网上有很多方法,在Mac和windows中都有安装包进行一键安装即可,在此就不多加赘述了。
1.2 源码获取
首先我们去github上apollo的官方仓库中获取部署需要的文件,注意除了使用git获取到源码,还需要在Releases页面中获取以下三个服务的最新稳定版本压缩包,用于后续的镜像构建。
- apollo-configservice
- apollo-adminservice
- apollo-portal
1.3 Mysql数据库
Apollo服务端共需要两个数据库:ApolloPortalDB和ApolloConfigDB,官网把数据库、表的创建和样例数据都分别准备了sql文件(在下载的源码包的script/sql目录下),只需要导入数据库即可。
建议后续使用已有的mysql进行部署不要将mysql不要和apollo的三个服务放在一个docker compose进行编排。因为我们要部署的服务在启动时需要依赖数据库中的配置,如果在一起编排服务,第一次启动会直接挂掉,mysql启动后还需要初始化才能正常使用,大家如果没有现成的mysql要使用docker构建,也建议部署好mysql导入sql文件后再启动apollo的服务。
1.4 部署策略
分布式部署需要事先确定部署的环境以及部署方式。Apollo目前支持以下环境:
- DEV 开发环境
- FAT 测试环境,相当于alpha环境(功能测试)
- UAT 集成环境,相当于beta环境(回归测试)
- PRO 生产环境
以ctrip为例,其部署策略如下:

- Portal部署在生产环境的机房,通过它来直接管理FAT、UAT、PRO等环境的配置
- Meta Server、Config Service和Admin Service在每个环境都单独部署,使用独立的数据库
- Meta Server、Config Service和Admin Service在生产环境部署在两个机房,实现双活
-
Meta Server和Config Service部署在同一个JVM进程内,Admin Service部署在同一台服务器的另一个JVM进程内
样例部署图.png
为了演示方便,本文将Apollo-portal,Apollo-adminservice和Apollo-configservice部署在一台机器上
服务器 服务 端口 环境
192.168.20.198 apollo-portal 8070 UAT
192.168.20.198 apollo-adminservice 8080 UAT
192.168.20.198 apollo-configservice 8090 UAT
二、构建镜像
首先创建一个apollo目录用于后续统一管理我们的资源文件,并创建apollo-configservice、apollo-adminservice、apollo-portal三个子目录。
打开之前下载源码,分别找出apollo-configservice/src/main/docker/Dockerfile、apollo-adminservice/src/main/docker/Dockerfile、apollo-portal/src/main/docker/Dockerfile三个文件并移动到之前创建的三个对应子目录下,将下载好的apollo-configservice-x.x.x-github.zip、apollo-adminservice-x.x.x-github.zip、apollo-portal-x.x.x-github.zip也一并移动到对应的子目录。
此处有了源码后如果有需求的话其实是可以自己进行打包的,但由于在本文中没有特殊需求,并且我自己在尝试打包中出现了各种依赖问题所以就放弃,如果各位有兴趣可以自行尝试。
准备好的目录结构如下:

部署时使用的是官方最新的1.7.1 release版本,中间出现了些状况为了看里面的源码所以我解压了压缩包,各位如果没有必要可以不解压。
以apollo-configservice为例,首先我们来看一下官方提供的Dockerfile:

可以看出在Dockerfile里就是一个标准的jar包部署内容,值得注意的是需要所需的jar包是从.zip压缩包解压出来的,这里直接使用之前下载的压缩包,但需要将Dockerfile中的${VERSION}改为实际下载的压缩包版本号
一切准本就绪后就可以进行镜像构建了:
cd apollo-configservice
docker build -t myhub/apollo-configservice .
cd apollo-adminservice
docker build -t myhub/apollo-adminservice .
cd apollo-portal
docker build -t myhub/apollo-portal .
将镜像推送至dockerHub:
#登录到dockerhub,首先得注册自己得账号
docker login -u yourname -p yourpassword docker.io
docker push myhub/apollo-configservice
docker push myhub/apollo-adminservice
docker push myhub/apollo-portal
至此准备工作就差不多了,接下来可以直接去要部署服务的目标服务器进行部署操作了
三、服务部署
首先编辑我们的docker-stack.yml文件,用于描述我们用docker stack部署服务的细节:
version: "3.7"
services:
apollo-configservice:
image: myhub/apollo-configservice:latest
ports:
- target: 8080
published: 8080
mode: host
environment:
- spring_datasource_url=jdbc:mysql://{mysqlurl}/ApolloConfigDB?characterEncoding=utf8
- spring_datasource_username={username}
- spring_datasource_password={password}
- eureka.instance.ip-address=192.168.20.198
deploy:
placement:
constraints:
- 'node.hostname == 192-168-20-198'
replicas: 1
update_config:
parallelism: 1
delay: 5s
failure_action: rollback
monitor: 60s
order: start-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 60s
rollback_config:
parallelism: 1
delay: 5s
failure_action: continue
monitor: 60s
order: start-first
apollo-adminservice:
image: myhub/gapi/apollo-adminservice:latest
ports:
- target: 8090
published: 8090
mode: host
environment:
- spring_datasource_url=jdbc:mysql://{mysqlurl}/ApolloConfigDB?characterEncoding=utf8
- spring_datasource_username={username}
- spring_datasource_password={password}
deploy:
placement:
constraints:
- 'node.hostname == 192-168-20-198'
replicas: 1
update_config:
parallelism: 1
delay: 5s
failure_action: rollback
monitor: 60s
order: start-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 60s
rollback_config:
parallelism: 1
delay: 5s
failure_action: continue
monitor: 60s
order: start-first
apollo-portal:
image: myhub/gapi/apollo-portal:latest
ports:
- target: 8070
published: 8070
mode: host
environment:
- DEV_META=http://192.168.20.198:8080
- spring_datasource_url=jdbc:mysql://{mysqlurl}/ApolloConfigDB?characterEncoding=utf8
- spring_datasource_username={username}
- spring_datasource_password={password}
deploy:
placement:
constraints:
- 'node.hostname == 192-168-20-198'
replicas: 1
update_config:
parallelism: 1
delay: 5s
failure_action: rollback
monitor: 60s
order: start-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 60s
rollback_config:
parallelism: 1
delay: 5s
failure_action: continue
monitor: 60s
order: start-first
需要注意的是,由于我们需要将三个服务都部署到192.168.20.198机器上,所以在deploy.placement.constraints中添加node.hostname == 192-168-20-198将服务都指定部署到192.168.20.198上。
之后由于客户端服务需要通过注册中心调用apollo-configservice服务拉去配置,所以在apollo-configservice中需要
添加环境变量- eureka.instance.ip-address=192.168.20.198将自己实际IP注册到eureka中,否则注册信息是docker内部网桥的虚拟地址,会导致我们拉去配置失败。
另外在apollo-portal需要添加环境变量- DEV_META=http://192.168.20.198:8080指定dev环境的configservice地址,官方提供的sql环境只开启了dev环境,开启其他环境在自后续进行说明
准备完成后就可以进行使用docker stack deploy命令部署服务了,但在此之前还需要到去ApolloConfigDB.ServerConfig表中将Key为eureka.service.url的Value由http://localhost:8080/eureka/改为http://192.168.20.198:8080/eureka/,因为apollo-configservice和apollo-adminservice服务都是通过此配置的地址注册到eureka中,configservice和注册中心在同一进程中没什么问题,但adminservice在其他容器中通过localhost:8080并不能找到configservice中但注册中心。
修改完成后运行命令以一键部署服务:
docker stack deploy -c docker-stack.yml apollo
完成后可以使用docker stack ps命令查看详情:
docker stack ps apollo
四、注意事项及后续升级
进行到这里我们的服务部署就基本完成了,为了便于演示暂时只是支持了官方开箱自带的dev环境,接下来演示如何增加新的环境。
