Docker 部署 3 节点 Nacos 集群(推荐 Compose 一键部署)
Nacos 集群必须依赖 MySQL 数据库(不能使用内置 Derby),且 3 个节点需共享同一 MySQL、容器间网络互通。本文提供 Docker Compose 一键部署(最简单)和 纯 Docker 命令分步部署 两种方案,单机多容器集群(测试环境),生产环境可替换为多服务器部署。
一、核心前提
-
已安装 Docker + Docker Compose
-
服务器开放端口:
8848、8849、8850(Nacos 端口)、3306(MySQL 端口) -
集群规划:
-
节点名称 容器IP 宿主映射端口 作用 nacos1 172.19.0.11 8848 集群节点1 nacos2 172.19.0.12 8849 集群节点2 nacos3 172.19.0.13 8850 集群节点3 mysql 172.19.0.10 3306 共享数据库
-
二、Docker Compose 一键部署(推荐)
1. 创建工作目录
# 创建集群工作目录
mkdir -p /docker/nacos-cluster
cd /docker/nacos-cluster
2. 创建 MySQL 初始化脚本
新建 nacos-mysql.sql(Nacos 官方数据库初始化脚本):
/*
* 官方SQL脚本:https://github.com/alibaba/nacos/blob/develop/distribution/conf/nacos-mysql.sql
*/
CREATE DATABASE IF NOT EXISTS 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 COMMENT 'group_id',
`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(50) DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`op_type` char(2) DEFAULT NULL COMMENT '操作类型',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_info';
/******************************************/
/* 表名称 = config_info_aggr */
/******************************************/
CREATE TABLE `config_info_aggr` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
`content` longtext NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='增加租户字段';
/******************************************/
/* 表名称 = config_info_beta */
/******************************************/
CREATE TABLE `config_info_beta` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
`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(50) DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_info_beta';
/******************************************/
/* 表名称 = config_info_tag */
/******************************************/
CREATE TABLE `config_info_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`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(50) DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_info_tag';
/******************************************/
/* 表名称 = config_tags_relation */
/******************************************/
CREATE TABLE `config_tags_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`nid` bigint(20) NOT NULL DEFAULT '0' COMMENT 'nid',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configtagrelation_configidtag` (`data_id`,`group_id`,`tenant_id`,`tag_name`,`tag_type`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='config_tag_relation';
/******************************************/
/* 表名称 = group_capacity */
/******************************************/
CREATE TABLE `group_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群、各Group容量信息表';
/******************************************/
/* 表名称 = his_config_info */
/******************************************/
CREATE TABLE `his_config_info` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`nid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'nid,分布式ID',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`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(50) DEFAULT NULL COMMENT 'source ip',
`op_type` char(2) DEFAULT NULL COMMENT '操作类型',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_gmt_modified` (`gmt_modified`),
KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多租户改造';
/******************************************/
/* 表名称 = tenant_capacity */
/******************************************/
CREATE TABLE `tenant_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户容量信息表';
/******************************************/
/* 表名称 = tenant_info */
/******************************************/
CREATE TABLE `tenant_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`tenant_id` varchar(128) NOT NULL COMMENT 'tenant_id',
`tenant_name` varchar(128) NOT NULL COMMENT 'tenant_name',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_info_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户信息表';
/******************************************/
/* 表名称 = users */
/******************************************/
CREATE TABLE `users` (
`username` varchar(50) NOT NULL COMMENT 'username',
`password` varchar(500) NOT NULL COMMENT 'password',
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态',
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
/******************************************/
/* 表名称 = roles */
/******************************************/
CREATE TABLE `roles` (
`username` varchar(50) NOT NULL COMMENT 'username',
`role` varchar(50) NOT NULL COMMENT 'role',
PRIMARY KEY (`username`,`role`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
/******************************************/
/* 表名称 = permissions */
/******************************************/
CREATE TABLE `permissions` (
`role` varchar(50) NOT NULL COMMENT 'role',
`resource` varchar(255) NOT NULL COMMENT 'resource',
`action` varchar(8) NOT NULL COMMENT 'action',
PRIMARY KEY (`role`,`resource`,`action`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表';
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$tHW.dXz9x0cJ7g42L1R6X.2s0aG4t0eG8eQ8eQ8eQ8eQ8eQ8eQ8e', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
3. 编写 Compose 编排文件
新建 docker-compose.yml:
version: '3.8'
# 自定义固定IP网络(容器间互通)
networks:
nacos-net:
driver: bridge
ipam:
config:
- subnet: 172.19.0.0/16
# 数据卷持久化
volumes:
mysql-data:
nacos1-data:
nacos2-data:
nacos3-data:
services:
# MySQL 服务
mysql:
image: mysql:5.7
container_name: nacos-mysql
networks:
nacos-net:
ipv4_address: 172.19.0.10
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root123456 # MySQL root密码
MYSQL_DATABASE: nacos_config # 自动创建Nacos数据库
volumes:
- mysql-data:/var/lib/mysql
- ./nacos-mysql.sql:/docker-entrypoint-initdb.d/nacos-mysql.sql # 初始化脚本
restart: always
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
# Nacos 节点1
nacos1:
image: nacos/nacos-server:v2.3.0
container_name: nacos1
networks:
nacos-net:
ipv4_address: 172.19.0.11
ports:
- "8848:8848"
- "9848:9848" # gRPC端口
environment:
MODE: cluster # 集群模式
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: 172.19.0.10
MYSQL_SERVICE_DB_NAME: nacos_config
MYSQL_SERVICE_PORT: 3306
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_PASSWORD: root123456
NACOS_SERVERS: 172.19.0.11:8848,172.19.0.12:8848,172.19.0.13:8848 # 集群节点
JVM_XMS: 512m
JVM_XMX: 512m
volumes:
- nacos1-data:/home/nacos/data
restart: always
depends_on:
mysql:
condition: service_healthy
# Nacos 节点2
nacos2:
image: nacos/nacos-server:v2.3.0
container_name: nacos2
networks:
nacos-net:
ipv4_address: 172.19.0.12
ports:
- "8849:8848"
- "9849:9848"
environment:
MODE: cluster
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: 172.19.0.10
MYSQL_SERVICE_DB_NAME: nacos_config
MYSQL_SERVICE_PORT: 3306
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_PASSWORD: root123456
NACOS_SERVERS: 172.19.0.11:8848,172.19.0.12:8848,172.19.0.13:8848
JVM_XMS: 512m
JVM_XMX: 512m
volumes:
- nacos2-data:/home/nacos/data
restart: always
depends_on:
mysql:
condition: service_healthy
# Nacos 节点3
nacos3:
image: nacos/nacos-server:v2.3.0
container_name: nacos3
networks:
nacos-net:
ipv4_address: 172.19.0.13
ports:
- "8850:8848"
- "9850:9848"
environment:
MODE: cluster
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: 172.19.0.10
MYSQL_SERVICE_DB_NAME: nacos_config
MYSQL_SERVICE_PORT: 3306
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_PASSWORD: root123456
NACOS_SERVERS: 172.19.0.11:8848,172.19.0.12:8848,172.19.0.13:8848
JVM_XMS: 512m
JVM_XMX: 512m
volumes:
- nacos3-data:/home/nacos/data
restart: always
depends_on:
mysql:
condition: service_healthy
4. 启动集群
# 后台启动
docker-compose up -d
# 查看容器状态(确保4个容器都为 Up)
docker-compose ps
三、纯 Docker 命令分步部署(手动)
1. 创建自定义网络
docker network create --subnet=172.19.0.0/16 nacos-network
2. 启动 MySQL 容器
docker run -d \
--name nacos-mysql \
--network nacos-network \
--ip 172.19.0.10 \
-p 3306:3306 \
-v mysql-data:/var/lib/mysql \
-v /docker/nacos-cluster/nacos-mysql.sql:/docker-entrypoint-initdb.d/nacos-mysql.sql \
-e MYSQL_ROOT_PASSWORD=root123456 \
-e MYSQL_DATABASE=nacos_config \
--restart always \
mysql:5.7
3. 启动 3 个 Nacos 节点
# 节点1
docker run -d \
--name nacos1 \
--network nacos-network \
--ip 172.19.0.11 \
-p 8848:8848 \
-p 9848:9848 \
-e MODE=cluster \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=172.19.0.10 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root123456 \
-e NACOS_SERVERS=172.19.0.11:8848,172.19.0.12:8848,172.19.0.13:8848 \
-v nacos1-data:/home/nacos/data \
--restart always \
nacos/nacos-server:v2.3.0
# 节点2
docker run -d \
--name nacos2 \
--network nacos-network \
--ip 172.19.0.12 \
-p 8849:8848 \
-p 9849:9848 \
-e MODE=cluster \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=172.19.0.10 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root123456 \
-e NACOS_SERVERS=172.19.0.11:8848,172.19.0.12:8848,172.19.0.13:8848 \
-v nacos2-data:/home/nacos/data \
--restart always \
nacos/nacos-server:v2.3.0
# 节点3
docker run -d \
--name nacos3 \
--network nacos-network \
--ip 172.19.0.13 \
-p 8850:8848 \
-p 9850:9848 \
-e MODE=cluster \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=172.19.0.10 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root123456 \
-e NACOS_SERVERS=172.19.0.11:8848,172.19.0.12:8848,172.19.0.13:8848 \
-v nacos3-data:/home/nacos/data \
--restart always \
nacos/nacos-server:v2.3.0
四、集群验证
1. 访问 Nacos 控制台
任意节点地址均可访问(默认账号密码:nacos/nacos):
2. 查看集群节点
登录控制台 → 左侧菜单 集群管理 → 节点列表,能看到 3 个 UP 状态的节点,说明集群部署成功。
3. 命令行验证
# 查看节点状态
docker logs nacos1 | grep "Nacos started successfully"
五、关键注意事项
- 集群必须用 MySQL:内置 Derby 仅支持单机,集群必须共享 MySQL
- 固定容器 IP:自定义网络+固定IP,避免容器重启IP变化导致集群失效
- 端口映射:宿主端口不能冲突(8848/8849/8850),同时开放 gRPC 端口(9848/9849/9850)
- 持久化:数据卷挂载,避免容器删除数据丢失
- 生产环境:单机集群仅用于测试,生产需3台独立服务器部署,搭配 Nginx 负载均衡
- 内存配置:JVM 参数
JVM_XMS/JVM_XMX根据服务器配置调整(最低 256m)
六、集群管理常用命令
# 重启集群
docker-compose restart
# 停止集群
docker-compose down
# 查看日志
docker-compose logs -f nacos1
总结
- 采用 Docker Compose 一键部署 3 节点 Nacos 集群,配置简单、不易出错
- 核心依赖:自定义固定IP网络 + 共享 MySQL 数据库
- 验证方式:控制台节点列表查看 3 个 UP 节点
- 单机集群用于测试,生产需多机部署 + 负载均衡