CentOS8中使用docker-compose部署Nacos集群

1. 前言

前面学习了 SpringCloudAlibaba之服务注册与发现Nacos 以及 SpringCloudAlibaba之配置中心Nacos,其中Nacos服务都部署在本地,那么现在把它部署到服务器上。

在服务器上部署Nacos,有多种方式,

单机:

方式一: 拷贝三份编译后的 Nacos Server,分别修改端口,以及编写 cluster.conf 文件

方式二: 启动三个 Nacos Server 的 Docker 容器

方式三: 使用 docker-compose 编排三个 Nacos Server 服务

三台及以上:

方式一: 每台都拷贝一份编译后的 Nacos Server,以及编写 cluster.conf 文件

方式二: 每台都启动一个 Nacos Server 的 Docker 容器

方式三: 每台都使用 docker-compose 编排一个 Nacos Server 服务

最方便的当然是使用 docker-compose 来编排服务,本篇博客也是使用的 docker-compose 方式(单机)。这里除了会编排三个 Nacos Server 服务,还会增加 MySQL 服务和 Nginx 服务,这也是官方推荐的部署架构:

1、至少使用三个Nacos节点

2、使用MySQL作为数据源,方便观察数据存储的基本情况

3、使用Nginx作为统一入口,扩展节点的时候不影响后端应用

2. 源码:

GitHub 地址:https://github.com/intomylife/Docker

Docker Hub 地址:https://hub.docker.com/r/intomylife

3. 部署

整个部署所需要的文件都在 build 目录中

build/

├── hostname

│ ├── config

│ │ ├── mysql

│ │ │ └── my.cnf

│ │ └── nginx

│ │ └── nginx.conf

│ ├── data

│ │ ├── mysql

│ │ ├── nacos

│ │ └── nginx

│ ├── docker-compose-all.yaml

│ ├── docker-compose-config.yaml

│ ├── docker-compose-discovery.yaml

│ ├── docker-compose.yaml

│ ├── env

│ │ ├── mysql

│ │ │ └── mysql.env

│ │ └── nacos

│ │ └── nacos.env

│ ├── .env

│ ├── init

│ │ └── mysql

│ │ └── init.sql

│ ├── log

│ │ ├── mysql

│ │ ├── nacos1

│ │ ├── nacos2

│ │ ├── nacos3

│ │ └── nginx

│ ├── start.sh

│ └── stop.sh

└── ip

├── config

│ ├── mysql

│ │ └── my.cnf

│ └── nginx

│ └── nginx.conf

├── data

│ ├── mysql

│ ├── nacos

│ └── nginx

├── docker-compose-all.yaml

├── docker-compose-config.yaml

├── docker-compose-discovery.yaml

├── docker-compose.yaml

├── env

│ ├── mysql

│ │ └── mysql.env

│ └── nacos

│ └── nacos.env

├── .env

├── init

│ └── mysql

│ └── init.sql

├── log

│ ├── mysql

│ ├── nacos1

│ ├── nacos2

│ ├── nacos3

│ └── nginx

├── start.sh

└── stop.sh

a、hostname和ip两个目录分别对应 PREFER_HOST_MODE 两种模式

b、两种模式对应的部署方式完全一样,只有配置上有些许不同;下面以hostname为例详细说明

3.1 config

服务的配置文件

3.1.1 mysql - my.cnf

[client]
default-character-set=utf8mb4
 
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# 数据库唯一 ID,主从的标识号绝对不能重复。
server-id = 1

# 开启 bin-log,并指定文件目录和文件名前缀
# 如果要使用挂载的路径,必进入docker容器内设置权限,命令 : docker exec -it 容器id bash
#chown -R mysql:mysql /var/log/mysql/
#log-bin=/var/log/mysql/binlog
log-bin=binlog

# bin-log 日志文件格式,设置为 MIXED 可以防止主键重复。
binlog_format = mixed

[mysql]
default-character-set=utf8mb4

a、配置了字符集编码

b、开启了 bin-log

3.1.2 nginx - nginx.conf

... 省略部分 ...

        upstream dispense {
        server nacos1:8848;
        server nacos2:8848;
        server nacos3:8848;
    }

        server {
                listen       9000;
        server_name  localhost;
 
        #charset koi8-r;
 
        #access_log  logs/host.access.log  main;
 
        location / {
            proxy_pass   http://dispense;
            index  index.html index.htm;
        }
                ... 省略部分 ...
        }
... 省略部分 ...

a、修改监听端口为 9000

b、请求会被负载均衡到三个 Nacos Server 服务上

3.2 data

持久化服务产生的数据

3.3 env

服务中独立而又重复的配置

3.3.1 mysql - mysql.env

TZ=Asia/Shanghai
MYSQL_ROOT_HOST=%

a、配置了容器的时区

b、被允许连接的地址,%表示全部

3.3.2 nacos - nacos.env

TZ=Asia/Shanghai
JVM_XMS=512m
JVM_XMX=512m
JVM_XMN=256m
MODE=cluster
PREFER_HOST_MODE=hostname
NACOS_SERVERS=nacos1:8848 nacos2:8848 nacos3:8848
NACOS_AUTH_ENABLE=true
MYSQL_SERVICE_HOST=mysql
MYSQL_SERVICE_DB_NAME=nacos_config

1、配置了容器的时区

2、指定JVM各种内存大小

3、MODE 指定Nacos启动的模式,cluster 表示集群模式

4、PREFER_HOST_MODE 在我理解,表明Nacos会以什么方式来寻找自己的集群“伙伴”(peers),一共有两种方式:hostname / ip;① 如果指定为 ip,那么 NACOS_SERVERS 也必须指定的是一组 ip(所有Nacos的集群节点),注意这里比较坑的是,它默认会取Docker的 ip(docker0:172.17.0.1/16),这样会导致 ip 地址不固定,更者如果是多台服务器就压根不会在同一个网络中,所以还需要配置 NACOS_SERVER_IP 内网地址用来显示指定 ip;② 如果指定为 hostname,那么 NACOS_SERVERS 也必须指定的是一组 hostname(所有Nacos的集群节点),所以还需要配置docker-compose中service的 hostname 用来显示指定主机名

5、NACOS_AUTH_ENABLE 开启密码验证,即在后端应用中如果要连接 Nacos Server,就必须要配置有效的用户名和密码才允许连接

6、最后两个指定了连接 MySQL 的配置信息

3.4 .env

docker-compose 默认引入的文件,里面配置默认的环境变量

## version
MYSQL_VERSION=5.7
NACOS_VERSION=1.2.1
NGINX_VERSION=1.8
FIRST_VERSION=1.0.0
SECOND_VERSION=1.0.0
CONSUMER_VERSION=1.0.0
ORDER_VERSION=1.0.0
USER_VERSION=1.0.0

## pwd
MYSQL_SERVICE_USER=root
MYSQL_ROOT_PASSWORD=123456
NACOS_USER=nacos
NACOS_PASSWORD=nacos

## env
ORDER_ENV=dev
USER_ENV=dev

此文件的目的就是为了简化我们的配置,避免修改多处重复的配置信息

3.5 init

服务的初始化数据

3.5.1 mysql - init.sql

-- 创建数据库
DROP database IF EXISTS `nacos_config`;
CREATE DATABASE `nacos_config` default character set utf8mb4 collate utf8mb4_unicode_ci;
 
-- 切换数据库
USE nacos_config;

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info   */
/******************************************/
CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';

... 省略部分 ...

1、MySQL 的初始化 sql 语句

2、由于 Nacos Server 的数据源使用的是 MySQL,所以需要建这些基础表和插入一些基础数据

3.6 log

映射出服务的日志信息

3.7 .yaml

先来整体看一下,类似文件一共有四个:docker-compose.yaml,docker-compose-discovery.yaml,docker-compose-config.yaml,docker-compose-all.yaml

这些文件都有什么?

部署的核心是 Nacos Server 集群,相关内容全部在 docker-compose.yaml 文件中;而其他文件,都是用来部署后端应用的,它们主要测试 Nacos Server 集群是否真正部署成功;这些后端应用又包括Nacos的服务注册发现和配置中心,分别在 docker-compose-discovery.yaml 和 docker-compose-config.yaml 文件中;最后 docker-compose-all.yaml 文件包含 docker-compose-discovery.yaml + docker-compose-config.yaml 两个文件的内容

为什么拆分开?

原本都写在一个 .yaml,然而在启动的时候发现,配置中心服务启动总是失败,因为 Nacos Server 还未完全启动,配置中心服务获取不到对应的配置信息,就启动失败;那么拆开后,就可以使用脚本来控制启动的顺序

3.7.1 docker-compose.yaml

此次部署的核心文件

version: '3'

services:

    mysql:
        container_name: mysql
        image: mysql:${MYSQL_VERSION}
        env_file: 
            - env/mysql/mysql.env
        environment:
            MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
        ports:
            - "3306:3306"
        volumes:
            - ./config/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
            - ./init/mysql/:/docker-entrypoint-initdb.d/
            - ./data/mysql/:/var/lib/mysql/
            - ./log/mysql/:/var/log/mysql/
        command: [
            '--character-set-server=utf8mb4',
            '--collation-server=utf8mb4_unicode_ci'
        ]
        restart: always

    nacos1:
        hostname: nacos1
        container_name: nacos1
        image: nacos/nacos-server:${NACOS_VERSION}
        env_file: 
            - env/nacos/nacos.env
        environment:
            MYSQL_SERVICE_USER: ${MYSQL_SERVICE_USER}
            MYSQL_SERVICE_PASSWORD: ${MYSQL_ROOT_PASSWORD}
        ports:
            - "8000:8848"
        volumes:
            - ./data/nacos/:/home/nacos/data/
            - ./log/nacos1/:/home/nacos/logs/
        depends_on:
            - mysql
        restart: always

    nacos2:
        hostname: nacos2
        container_name: nacos2
        image: nacos/nacos-server:${NACOS_VERSION}
        env_file: 
            - env/nacos/nacos.env
        environment:
            MYSQL_SERVICE_USER: ${MYSQL_SERVICE_USER}
            MYSQL_SERVICE_PASSWORD: ${MYSQL_ROOT_PASSWORD}
        ports:
            - "8001:8848"
        volumes:
            - ./data/nacos/:/home/nacos/data/
            - ./log/nacos2/:/home/nacos/logs/
        depends_on:
            - mysql
        restart: always

    nacos3:
        hostname: nacos3
        container_name: nacos3
        image: nacos/nacos-server:${NACOS_VERSION}
        env_file: 
            - env/nacos/nacos.env
        environment: 
            MYSQL_SERVICE_USER: ${MYSQL_SERVICE_USER}
            MYSQL_SERVICE_PASSWORD: ${MYSQL_ROOT_PASSWORD}
        ports:
            - "8002:8848"
        volumes:
            - ./data/nacos/:/home/nacos/data/
            - ./log/nacos3/:/home/nacos/logs/
        depends_on:
            - mysql
        restart: always

    nginx:
        container_name: nginx
        image: nginx:${NGINX_VERSION}
        environment:
            TZ: Asia/Shanghai
        ports:
            - "9000:9000"
        volumes:
            - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
            - ./data/nginx/:/usr/share/nginx/html/
            - ./log/nginx/:/var/log/nginx/
        depends_on:
            - nacos1
            - nacos2
            - nacos3
        restart: always

1、三个Nacos节点,使用MySQL作为数据源,使用Nginx作为统一入口

2、${} 用来获取 .env 文件中的环境变量

3、env_file 指定环境变量文件,可同时引入多个环境变量,与 environment 中的环境变量结合使用;想知道哪些环境变量生效了,使用 docker-compose -f 文件名 config 命令来查看指定文件的具体内容

重点看下两种模式下,Nacos 的配置有哪些不同,分别进入到 hostname 目录和 ip 目录中,使用 docker-compose -f docker-compose.yaml config 命令来查看具体内容,片段如下:

hostname:

... 省略部分 ...
  nacos1:
    container_name: nacos1
    depends_on:
    - mysql
    environment:
      JVM_XMN: 256m
      JVM_XMS: 512m
      JVM_XMX: 512m
      MODE: cluster
      MYSQL_SERVICE_DB_NAME: nacos_config
      MYSQL_SERVICE_HOST: mysql
      MYSQL_SERVICE_PASSWORD: '123456'
      MYSQL_SERVICE_USER: root
      NACOS_AUTH_ENABLE: "true"
      NACOS_SERVERS: nacos1:8848 nacos2:8848 nacos3:8848
      PREFER_HOST_MODE: hostname
      TZ: Asia/Shanghai
    hostname: nacos1
    image: nacos/nacos-server:1.2.1
    ports:
    - 8000:8848/tcp
    restart: always
    volumes:
    - /usr/local/build/hostname/data/nacos:/home/nacos/data:rw
    - /usr/local/build/hostname/log/nacos1:/home/nacos/logs:rw
... 省略部分 ...

ip:

... 省略部分 ...
  nacos1:
    container_name: nacos1
    depends_on:
    - mysql
    environment:
      JVM_XMN: 256m
      JVM_XMS: 512m
      JVM_XMX: 512m
      MODE: cluster
      MYSQL_SERVICE_DB_NAME: nacos_config
      MYSQL_SERVICE_HOST: mysql
      MYSQL_SERVICE_PASSWORD: '123456'
      MYSQL_SERVICE_USER: root
      NACOS_APPLICATION_PORT: '8000'
      NACOS_AUTH_ENABLE: "true"
      NACOS_SERVERS: xxx.xxx.xxx.xxx:8000 xxx.xxx.xxx.xxx:8001 xxx.xxx.xxx.xxx:8002
      NACOS_SERVER_IP: xxx.xxx.xxx.xxx
      PREFER_HOST_MODE: ip
      TZ: Asia/Shanghai
    image: nacos/nacos-server:1.2.1
    ports:
    - 8000:8000/tcp
    restart: always
    volumes:
    - /usr/local/build/ip/data/nacos:/home/nacos/data:rw
    - /usr/local/build/ip/log/nacos1:/home/nacos/logs:rw
... 省略部分 ...

相同点:

1、指定JVM各种内存大小

2、指定MODE为集群模式

3、指定了MySQL连接信息

4、开启了密码验证

5、配置了容器的时区

6、映射了日志目录和数据目录

不同点:

1、最大的不同点,就是 PREFER_HOST_MODE 选择的模式:hostname / ip

2、hostname 模式: 需要配置service服务的 hostname -> hostname: nacos1;在指定 NACOS_SERVERS 集群地址时,就是一组 hostname -> nacos1:8848 nacos2:8848 nacos3:8848

3、ip 模式: 需要配置 NACOS_SERVER_IP -> NACOS_SERVER_IP: xxx.xxx.xxx.xxx;在指定 NACOS_SERVERS 集群地址时,就是一组 ip -> xxx.xxx.xxx.xxx:8000 xxx.xxx.xxx.xxx:8001 xxx.xxx.xxx.xxx:8002。这里需要注意的是,由于是在一台服务器中,那么端口是不能重复的,所以这时还要指定每一个 Nacos Server 的端口,即配置 NACOS_APPLICATION_PORT

4、端口映射的不同

注:ip 模式具体的地址和端口都在 build/ip/.env 文件中配置;如果这里修改了端口,那么同时也需要在 build/ip/config/nginx/nginx.conf 文件中修改负载中对应server的端口

3.7.2 docker-compose-all.yaml

用于测试 Nacos Server 集群的后端应用

docker-compose-all.yaml = docker-compose-discovery.yaml + docker-compose-config.yaml

version: '3'

services:

    first:
        container_name: first
        image: intomylife/nacos-cluster-first:${FIRST_VERSION}
        environment:
            TZ: Asia/Shanghai
            spring.cloud.nacos.discovery.server-addr: nginx:9000
            spring.cloud.nacos.discovery.username: ${NACOS_USER}
            spring.cloud.nacos.discovery.password: ${NACOS_PASSWORD}
        ports:
            - "8090:8090"
        restart: always

    second:
        container_name: second
        image: intomylife/nacos-cluster-second:${SECOND_VERSION}
        environment:
            TZ: Asia/Shanghai
            spring.cloud.nacos.discovery.server-addr: nginx:9000
            spring.cloud.nacos.discovery.username: ${NACOS_USER}
            spring.cloud.nacos.discovery.password: ${NACOS_PASSWORD}
        ports:
            - "8091:8091"
        restart: always

    consumer:
        container_name: consumer
        image: intomylife/nacos-cluster-consumer:${CONSUMER_VERSION}
        environment:
            TZ: Asia/Shanghai
            spring.cloud.nacos.discovery.server-addr: nginx:9000
            spring.cloud.nacos.discovery.username: ${NACOS_USER}
            spring.cloud.nacos.discovery.password: ${NACOS_PASSWORD}
        ports:
            - "8080:8080"
        restart: always

    order:
        container_name: order
        image: intomylife/nacos-cluster-order:${ORDER_VERSION}
        environment:
            TZ: Asia/Shanghai
            spring.cloud.nacos.config.server-addr: nginx:9000
            spring.cloud.nacos.config.username: ${NACOS_USER}
            spring.cloud.nacos.config.password: ${NACOS_PASSWORD}
            spring.cloud.nacos.config.group: ${ORDER_ENV}
            spring.cloud.nacos.discovery.server-addr: nginx:9000
            spring.cloud.nacos.discovery.username: ${NACOS_USER}
            spring.cloud.nacos.discovery.password: ${NACOS_PASSWORD}
        ports:
            - "10000:10000"
        restart: always

    user:
        container_name: user
        image: intomylife/nacos-cluster-user:${USER_VERSION}
        environment:
            TZ: Asia/Shanghai
            spring.cloud.nacos.config.server-addr: nginx:9000
            spring.cloud.nacos.config.username: ${NACOS_USER}
            spring.cloud.nacos.config.password: ${NACOS_PASSWORD}
            spring.cloud.nacos.config.group: ${USER_ENV}
            spring.cloud.nacos.discovery.server-addr: nginx:9000
            spring.cloud.nacos.discovery.username: ${NACOS_USER}
            spring.cloud.nacos.discovery.password: ${NACOS_PASSWORD}
        ports:
            - "11000:11000"
        restart: always

1、first,second和consumer服务是一组,实现了服务的注册与发现功能

2、order和user服务是一组,实现了配置中心功能

3、源码在这里获取

3.8 .sh

启动脚本和停止脚本

3.8.1 start.sh

#!/bin/bash
## $() - 方法,${} - 变量

## 获取入参,启动类型
start_type=$1
## 输出看一眼
echo start_type: ${start_type}

## 参数校验
if [ "$start_type" == "discovery" ]||[ "$start_type" == "config" ]||[ "$start_type" == "all" ];
then
    ## 先启动基础服务
    docker-compose -f docker-compose.yaml up -d

    ## 循环十次检查基础服务是否启动完成
    for((i=1;i<=10;i++));
    do
        ## 检查服务是否启动完成
        code=$(curl -o /dev/null -s -w %{http_code} 127.0.0.1:9000/nacos)
        if [ ${code} == '302' ];
        then
            echo 'check  ---  success  --- ' ${code};
            break;
        else
            echo 'check  ---  loading  --- ' ${code};
        fi
        ## 三秒中检查一次
        sleep 3;
    done

    ## 检查结束或检查终止,再次获取服务状态码
    code=$(curl -o /dev/null -s -w %{http_code} 127.0.0.1:9000/nacos)
    if [ ${code} == '302' ];
    then
        ## 启动完成,接着启动后端应用服务
        docker-compose -f docker-compose-$start_type.yaml up -d
        echo 'success';
    else
        ## 启动失败,可能出错了,停止基础服务
        docker-compose -f docker-compose.yaml down
        echo 'fail';
    fi
else
    ## 参数有误
    echo 'end';
fi

1、启动脚本

2、脚本还会获取一个入参,这个入参分别对应不同组合的后端应用服务:discovery,config,all

3、考虑到服务较多,如果你只想单纯的部署 Nacos Server 集群,那么就不需要关注这个启动脚本,直接docker-compose up -d即可

4、这个脚本为了解决配置中心服务启动失败问题,其中就循环检查 Nginx 服务的状态码,只有基础服务(Nacos Server 集群)完全启动成功,才会启动后端应用

3.8.2 stop.sh

#!/bin/bash
## $() - 方法,${} - 变量

## 停止服务
docker-compose -f docker-compose.yaml -f docker-compose-all.yaml down

停止脚本

3.9 启动

3.9.1 启动前的准备

1、获取源码

2、整个 build 目录上传到服务器上

3、以 hostname 模式为例,进入到 hostname 目录cd build/hostname

4、启动脚本赋予执行权限chmod +x start.sh

5、停止脚本赋予执行权限chmod +x stop.sh

6、日志目录赋予读写执权限chmod -R 777 log/

3.9.2 启动

1、如果只需要 Nacos Server 集群,那么在 hostname 目录下执行命令docker-compose up -d

2、如果需要 Nacos Server 集群 + 服务注册与发现,那么在 hostname 目录下执行命令./start.sh discovery

3、如果需要 Nacos Server 集群 + 配置中心,那么在 hostname 目录下执行命令./start.sh config

4、如果都需要,那么在 hostname 目录下执行命令./start.sh all

5、整个启动过程大概在一分钟左右

6、等待出现success表示启动成功,接下来进行访问(如果有防火墙,注意开放端口:3306,8000,8001,8002,9000,8090,8091,8080,10000,11000)

7、访问地址 ip:9000/nacos,进入到 Nacos Server 主页面

8、账号密码:nacos, nacos

9、进入 集群管理 - 节点列表 页面,有如下数据,则表示集群搭建成功

节点Ip 节点状态 集群任期 Leader止时(ms) 心跳止时(ms)

nacos1:8848 LEADER 1 13849 2500

nacos2:8848 FOLLOWER 1 14338 2500

nacos3:8848 FOLLOWER 1 12273 2500

10、测试服务注册与发现,多次访问地址 ip:8080/feign,可以发现轮流输出Hello Spring Cloud Alibaba!!! port:8090和Hello Spring Cloud Alibaba!!! port:8091

11、测试配置中心,访问地址 ip:10000/info,可以看到输出内容dataInfo: order-config-dev.yml, group: dev, extName: mysql-dev

12、如果你还想在本地项目连接此 Nacos Server 集群,那么下载源码,修改配置文件中的server-addr为你的 ip:9000 即可

13、如果想测试 ip 模式,那么需要先在 build/ip/.env 文件中的 NACOS_SERVER_IP 处配置你自己的内网 ip;然后再进入到 ip 目录,执行上面相同的命令

3.9.3 停止

在 hostname 目录下执行命令./stop.sh

4. 参考

https://nacos.io/zh-cn/docs/quick-start-docker.html

https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html

https://github.com/nacos-group/nacos-docker