Docker 部署 Nacos 集群
1. 准备镜像
既然是部署 Nacos 集群,那么必须准备 Nacos 镜像 。
Nacos 默认内置一个 Derby 数据库,在集群模式中需要统一数据源,所以这边还需要一个 mysql 镜像
集群部署完毕之后,我们可以通过 ip:port
的方式访问集群中每一台机器。但是集群作为一个整体,更好地方式是通过 NGINX 做一个负载均衡,然后把访问均匀的打到不同的机器上。所以本文中还引入了一个 NGINX 镜像。
- Nacos 镜像:https://hub.docker.com/r/nacos/nacos-server
- MySQL 镜像 https://hub.docker.com/_/mysql/tags?page=1&ordering=-last_updated
- Nginx 镜像:https://hub.docker.com/_/nginx
docker pull nginx
docker pull nacos/nacos-server
docker pull mysql:5.7.5
macOS 用户需要注意
需要注意的是,如果你的机器是 apple silicon m1 (pro/max) 的芯片,请使用支持 arm 架构的 nacos,我这边用的是 chenfengwei/nacos。如果使用 nacos:latest 则无法启动集群模式,nginx 我用的 homebrew 安装的,没用 docker 启动 NGINX。
docker pull chenfengwei/nacos:v1
配置 docker network
首先需要保证 Nacos 集群中各台主机能够互联互通,因为Nacos 集群中每台主机需要与其他主机通信。且不能通过 ip:port
的方式配置 cluster.conf
文件,除非能够保证集群中每台机器的 ip 地址不变。
为了实现容器内网络互通,并且给每台机器配置一个 hostname 的功能,需要使用到 docker network create
指令创建一个 bridge
类型的网络配置。
docker network create nacos
后续启动 nacos 服务时,都需要加上一个参数:--network nacos
。
Docker 命令行启动集群服务
启动 MySQL 服务
首先启动一台 MySQL 服务,由于 docker 容器在停止之后,存储到容器之中的数据不容易迁移,并且在删除镜像后还会丢失数据。此处选择将 mysql 的数据存储地址通过 -v
参数挂载到本机上。
通过 docker volume
来管理容器与宿主机之间的数据挂载,首先创建一个 docker volume
docker volume create nacos_persistence_mysql
同时也要保证 Nacos 集群中的机器能够访问 Nacos,所以在启动 MySQL 服务时也需要加上参数 --network nacos
。
docker run -d -p 13306:3306 \
--network nacos \
-v nacos_persistence_mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=11111111 \
--name nacos_db mysql:5.7.5
--network nacos
使用前面创建的network nacos 。-v nacos_persistence_mysql:/var/lib/mysql
将 MySQL 容器内的数据挂载到刚刚创建的虚拟卷 。nacos_persistence_mysql
中。-e MYSQL_ROOT_PASSWORD=11111111
设置 root 用户的密码。--name nacos_db
设置容器名称,该名称也会作为在 networknacos
中的主机名 (hostname)。
启动 Nacos 集群
为了启动集群,首先要创建 cluster.conf
,并通过 -v
参数挂载到容器内部的 conf
目录下。cluster.conf
中的 ip 不能使用具体的 ip 地址,而是要使用容器的 hostname,既 docker run
命令中的 --name
参数值。
这里配置的内容为:
/etc/docker/containers_conf/nacos/cluster.conf内容如下:
nacos1:8848
nacos2:8848
nacos3:8848
根据配置文件中的内容,后面启动的三个Nacos
镜像的 --name
属性分别为 nacos1
、nacos2
、nacos3
。且 --network
值都为 nacos。
启动好 MySQL 之后,以集群模式启动 3 台 Nacos 服务。
Nacos 服务1
docker run --name nacos1 -d --network nacos -p 18848:8848 \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=nacos_db \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=11111111 \
-v /etc/docker/containers_conf/nacos/cluster.conf:/home/nacos/conf/cluster.conf nacos/nacos-server
Nacos 服务2
docker run --name nacos2 -d --network nacos -p 28848:8848 \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=nacos_db \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=11111111 \
-v /etc/docker/containers_conf/nacos/cluster.conf:/home/nacos/conf/cluster.conf nacos/nacos-server
Nacos 服务3
docker run --name nacos3 -d --network nacos -p 38848:8848 \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=nacos_db \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=11111111 \
-v /etc/docker/containers_conf/nacos/cluster.conf:/home/nacos/conf/cluster.conf nacos/nacos-server
--name nacos3
指定容器名和在 network nacos 中的 hostname。-e SPRING_DATASOURCE_PLATFORM=mysql
指定 NACOS 持久化选择 mysql。-e MYSQL_SERVICE_HOST=nacos_db
指定使用的 mysql 服务器主机名,既前面启动 mysql 容器是指定的--name
参数。-e MYSQL_SERVICE_DB_NAME=nacos
使用哪个数据库、-e MYSQL_SERVICE_USER=root
登录 mysql 的用户名、-e MYSQL_SERVICE_PASSWORD=11111111
登录 mysql 的密码。-v /etc/docker/containers_conf/nacos/cluster.conf:/home/nacos/conf/cluster.conf
挂载主机的集群配置文件。
此时访问 localhost 的 18848
、28848
、38848
端口即可访问到 nacos 集群,并且在任意一个 nacos 服务上创建配置,在另外两台 nacos 服务上都能看到创建的配置。
启动 Nginx
上一节我们启动了三个 Nacos 容器,分别映射到主机的 18848
、28848
、38848
三个端口。当我们后续访问时,肯定不会通过端口来访问不同的 Nacos 服务(因为这样做还是单兵作战,没有统筹作战)。
所以我们还需要一个 Nginx 来做负载均衡,来讲请求均匀的打到三个 Nacos 服务上。
需要注意的是,这个 Nginx 容器也要使用和前面三台 Nacos 服务和 MySQL 一样的 --network
设置。下面是用来挂载到 Nginx 容器中的 Nginx 配置文件内容:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#access_log logs/access.log main;
sendfile on;
keepalive_timeout 65;
# ############ 注意这里 #############
# nacos1、nacos2、nacos3分别对于上一节启动的 nacos 容器的 --name 参数,也就是 在 --network=nacos 网络配置中的主机名
upstream cluster{
server nacos1:8848;
server nacos2:8848;
server nacos3:8848;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
# ############ 注意这里 #############
# 将请求打到 cluster
location /nacos {
proxy_pass http://cluster;
}
location / {
root html;
index index.html index.htm;
}
}
}
docker run -d -p 80:80 --network nacos -v ./nginx.conf:/etc/nginx/nginx.conf --name nginx_nacos nginx
收工
此时即可通过 80 端口的 /nacos/nacos
路径访问到 Nacos 服务了!!!
docker compose 编排 Nacos 集群
上面的方式虽说也能用,但是要分别启动最少三个nacos镜像、最少一台MySQL和最少一台Nginx。而且 nacos 的配置项(-e
) 很多,每次敲起来简直怀疑人生。这里我将 docker compose 的 yml 文件贴出来。
需要注意,如果 Nacos 使用 MySQL 进行配置数据的存储,那么一定要保证 MySQL 容器内有对应的数据库和表。那么如何在 MySQL 容器首次启动时就把这些表建好呢?MySQL 的官方镜像提供了一个初始化的方式,通过将 .sql
文件挂载到镜像内部的docker-entrypoint-initdb.d
文件夹内,MySQL 就会在容器内部的 /var/lib/mysql
文件夹为空的情况下运行我们的 .sql
文件了。有图为证:
只有在 /var/lib/mysql
文件夹为空时才能执行 docker-entrypoint-initdb.d
文件夹内的 .sh
、.sql
、.sql.gz
文件,证明在此 ,查看 402 行和 259 行。
version: "2.6.0"
networks:
nacos_cluster:
name: compose_nacos_cluster
services:
mysql:
image: mysql:5.7.5
environment:
MYSQL_ROOT_PASSWORD: 11111111
volumes:
# 将 MySQL 数组存储文件夹挂载到宿主机
- /var/lib/docker/mysql:/var/lib/mysql
networks:
- nacos_cluster
ports:
- 13306:3306
command: --default-authentication-plugin=mysql_native_password&allowPublicKeyRetrieval=true
nacos2:
image: nacos/nacos-server
hostname: nacos2
ports:
- 28848:8848
environment:
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: mysql
MYSQL_SERVICE_DB_NAME: nacos
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_PASSWORD: 11111111
volumes:
# nacos 集群配置文件的挂载
- /etc/docker/containers_conf/nacos/cluster.conf:/home/nacos/conf/cluster.conf
# 若 MySQL 容器第一次启动,那么数据库中一定没有建 Nacos 的库和表。将 Nacos 的初始化 sql 挂载到镜像内的 docker-entrypoint-initdb.d 文件夹内,这样 MySQL 容器在首次启动时就会执行这个 .sql 文件。
- nacos-init.sql:/docker-entrypoint-initdb.d/nacos-init.sql
networks:
- nacos_cluster
depends_on:
- mysql
nacos1:
image: nacos/nacos-server
hostname: nacos1
ports:
- 18848:8848
environment:
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: mysql
MYSQL_SERVICE_DB_NAME: nacos
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_PASSWORD: 11111111
volumes:
# nacos 集群配置文件的挂载
- /etc/docker/containers_conf/nacos/cluster.conf:/home/nacos/conf/cluster.conf
networks:
- nacos_cluster
depends_on:
- mysql
nacos3:
image: nacos/nacos-server
hostname: nacos3
ports:
- 38848:8848
environment:
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: mysql
MYSQL_SERVICE_DB_NAME: nacos
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_PASSWORD: 11111111
volumes:
# nacos 集群配置文件的挂载
- /etc/docker/containers_conf/nacos/cluster.conf:/home/nacos/conf/cluster.conf
networks:
- nacos_cluster
depends_on:
- mysql
web:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "80:80"
networks:
- nacos_cluster
depends_on:
- mysql
- nacos1
- nacos2
- nacos3