分布式配置中心 Apollo 的使用(一)构建 Apollo 的 Docker 容器镜像并连接到现有数据库

优化之前组的 K3s 集群的时候,想到每次配置文件的小修小改都要重启一大堆容器实在麻烦,只怪最初没考虑完全,趁这次机会起一个配置中心来解决这个麻烦。


① 什么是配置中心?
配置中心将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去管理配置,可以参考下图:
配置中心
② 为什么选择 Apollo?
携程开源且 GitHub 更新勤快,截止 2022 年 1 月 5 日还在更新。
具体可以参照这篇文章:分布式配置中心(Nacos、Apollo)选型比较


Apollo 的运行需要 8 GB 左右的内存,如果你的服务器配置低于 2 核 8 GB,那就不用尝试了。
官方给了 2 种方式来部署 Apollo:在服务器中直接启动和使用 Docker 启动,在服务器中直接启动就不用说了,而官方所使用的 Docker 镜像:nobodyiam/apollo-quick-start 是自带 MySQL 数据库的,我并不需要,于是就只能自己构建了。
我希望最终容器可以和 apolloconfig/apollo-configservice 启动命令一样(并不是官方镜像因此不使用),能够指定数据库连接。
我的 Dockerfile 文件:Apollo-docker
我构建完的 Docker 镜像:rabbir/apollo

1、安装和配置 Apollo 运行环境

官方描述的运行环境:

  • Linux
  • JDK(1.8 以上,推荐 1.8)
  • MySQL(5.65 及以上,我有外置的数据库因此不做安装

① 直接拉取一个 CentOS7 的镜像:

# 拉取镜像
docker pull centos:centos7
# 运行镜像
docker run -it docker.io/centos:centos7 /bin/bash

之后的命令都是在容器内执行!

② 安装 JDK1.8:

# 安装位置
cd /usr/local/
yum -y install wget
# 下载压缩包
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie"  http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
# 解压并重命名
tar -zxvf jdk-8u131-linux-x64.tar.gz
mv jdk1.8.0_131 jdk1.8
# 删除压缩包
rm -f jdk-8u131-linux-x64.tar.gz
# 配置环境变量
vi ~/.bashrc

新增以下两行:

...
...
# Java 相关
export JAVA_HOME=/usr/local/jdk1.8
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
...
...

Java 配置
使配置生效:

source ~/.bashrc
# 确认 Java 版本
java -version

Java 版本

2、下载 Apollo Quick Start 安装包
官方文档中对应的位置:下载 Quick Start 安装包
项目地址:nobodyiam/apollo-build-scripts

yum -y install git
# 克隆项目
git clone https://github.com/nobodyiam/apollo-build-scripts

修改一下 demo.sh 使其能从环境变量中读取数据库连接信息:

sed -i 's#jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai#$APOLLO_CONFIG_DB_JDBC#' /usr/local/apollo-build-scripts/demo.sh
sed -i 's#"dbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai#$APOLLO_PORTAL_DB_JDBC#' /usr/local/apollo-build-scripts/demo.sh

原本的片段:

# apollo config db info
apollo_config_db_url="jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai"
apollo_config_db_username=${APOLLO_CONFIG_DB_USERNAME:-root}
apollo_config_db_password=${APOLLO_CONFIG_DB_PASSWORD:-}

# apollo portal db info
apollo_portal_db_url="jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai"
apollo_portal_db_username=${APOLLO_PORTAL_DB_USERNAME:-root}
apollo_portal_db_password=${APOLLO_PORTAL_DB_PASSWORD:-}

修改后的片段:

# apollo config db info
apollo_config_db_url="$APOLLO_CONFIG_DB_JDBC"
apollo_config_db_username=${APOLLO_CONFIG_DB_USERNAME:-root}
apollo_config_db_password=${APOLLO_CONFIG_DB_PASSWORD:-}

# apollo portal db info
apollo_portal_db_url="$APOLLO_PORTAL_DB_JDBC"
apollo_portal_db_username=${APOLLO_PORTAL_DB_USERNAME:-root}
apollo_portal_db_password=${APOLLO_PORTAL_DB_PASSWORD:-}

3、构建 Docker 容器镜像并运行
① 配置一下 Apollo 运行所需要的数据库结构,需要新增两个 DB:ApolloPortalDBApolloConfigDB,文档中的位置:2.1 创建数据库
我是买的腾讯云数据库,因此直接在网页端执行(需要手动创建数据库后选定数据库执行剩下的语句,部分 SET 语句出错可以跳过):
执行 SQL 之后检查一下:

-- 检查 ApolloPortalDB
select `Id`, `AppId`, `Name` from ApolloPortalDB.App;
Id AppId Name
1 SampleApp Sample App
ApolloConfigDB 同理,创建数据库并建表之后检查:
-- 检查 ApolloConfigDB
select `NamespaceId`, `Key`, `Value`, `Comment` from ApolloConfigDB.Item;
NamespaceId Key Value Comment
1 timeout 100 sample timeout配置

② 将上述所有命令写入 Dockerfile(部分命令如环境变量的配置会有所不同):

# 基础镜像系统版本为 CentOS:7
FROM centos:7

# 维护者信息
LABEL maintainer="Rabbir [email protected]"

# Docker 内用户切换到 root
USER root

# 设置时区为东八区
ENV TZ Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime > /etc/timezone

# 安装 Git 和 Wget
RUN yum -y install wget
RUN yum -y install git

# 切换到 /usr/local/ 目录下
WORKDIR /usr/local/
# 下载解压 JDK
RUN wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie"  http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
RUN tar -zxvf jdk-8u131-linux-x64.tar.gz
RUN mv jdk1.8.0_131  jdk1.8
RUN rm -f jdk-8u131-linux-x64.tar.gz

# 添加容器内的永久环境变量
RUN sed -i "2 a export JAVA_HOME=/usr/local/jdk1.8" /etc/profile
RUN sed -i "3 a export PATH=\$PATH:\$JAVA_HOME/bin" /etc/profile
RUN sed -i "4 a export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar" /etc/profile
RUN source /etc/profile
RUN sed -i '1 a source /etc/profile' ~/.bashrc
RUN source ~/.bashrc

# 添加构建用的临时环境变量
ENV JAVA_HOME /usr/local/jdk1.8
ENV PATH $PATH:$JAVA_HOME/bin
ENV CLASSPATH .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

# 克隆源码并修改 demo.sh 文件
WORKDIR /usr/local/
RUN git clone https://github.com/nobodyiam/apollo-build-scripts
WORKDIR /usr/local/apollo-build-scripts/
RUN sed -i 's#jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai#$APOLLO_CONFIG_DB_JDBC#' demo.sh
RUN sed -i 's#jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai#$APOLLO_PORTAL_DB_JDBC#' demo.sh

# 创建启动脚本
RUN echo "/bin/bash /usr/local/apollo-build-scripts/demo.sh start && tail -f /dev/null" > start.sh

# 启动命令
ENTRYPOINT ["/bin/bash", "start.sh"]
CMD [""]

构建(镜像名和版本自行替换):

docker build -t rabbir/apollo:latest .

③ 启动并登录管理界面
Apollo 启动会用到三个端口:

  • 8070(Apollo Portal 管理界面端口)
  • 8080(提供配置的读取、推送等功能,服务对象是 Apollo 的各客户端)
  • 8090(提供配置的修改、发布等功能,服务对象是 Apollo Portal)

暂时不做文件夹的映射,因此启动命令如下(数据库连接信息自行更改):

docker run --name apollo -d \
	-p 18070:8070 \
    -p 18080:8080 \
    -p 18090:8090 \
    -e APOLLO_CONFIG_DB_JDBC="jdbc:mysql://127.0.0.1:3306/ApolloConfigDB?characterEncoding=utf8" \
    -e APOLLO_CONFIG_DB_USERNAME="myusername" \
    -e APOLLO_CONFIG_DB_PASSWORD="mypassword" \
    -e APOLLO_PORTAL_DB_JDBC="jdbc:mysql://127.0.0.1:3306/ApolloPortalDB?characterEncoding=utf8" \
    -e APOLLO_PORTAL_DB_USERNAME="myusername" \
    -e APOLLO_PORTAL_DB_PASSWORD="mypassword" \
	rabbir/apollo:latest

启动并查看日志:

docker logs apollo

启动成功
显示如上则说明没有问题,确保防火墙和安全组开放的情况下就能去访问管理界面了,登录账号为 apollo 密码为 admin(我将容器的 8070 端口映射到了宿主机的 18070 端口上):
访问成功
登录成功

成功,结束。