做微服务这套东西,注册中心和配置中心基本绕不开Nacos。从2.x用到3.x,我的直观感受是:3.x的控制台好看了、gRPC链路更稳定,但Docker部署的坑一个没少——端口、内存、数据库、鉴权,随便一个没配好都能给你颜色看。
这篇文章是架构环境安装系列的第四篇,我会按实际部署顺序,把Docker安装Nacos3.x的完整流程走一遍:单机怎么起、MySQL怎么接、集群怎么组,以及我踩过的那些坑。不是只贴几条docker命令,而是把每条命令背后的参数为什么这么写讲清楚,方便你拿到新版本镜像时不至于对着文档发呆。
适合谁看?准备在开发环境快速搭Nacos、或者打算在生产环境用容器化方式部署Nacos的兄弟。新手能照着操作成功,老手也能对照检查有没有漏掉的细节。我先把结论放这儿:这版本折腾人的地方不在镜像本身,而在端口规划和数据持久化,这两块搞明白,部署就顺了。
1. 部署前先想清楚三件事
1.1 选对Nacos版本和镜像
现在写这篇,Nacos已经到3.x稳定版。去Docker Hub拉镜像时,直接指定版本号,不要用latest。拉镜像命令:
bash复制docker pull nacos/nacos-server:v3.0.3
v3.0.3是我在写这篇时确认可用的版本,如果你看的时候已经出了3.1.x,命令参数保持不变,把版本号换掉就行。我见过不少人拉了个latest,过两天镜像更新,环境变量和默认配置变了,服务莫名起不来。版本固定下来,至少你的生产环境是可控的。如果想把镜像留一份在私有环境,Docker有save和load两条命令:
bash复制docker save nacos/nacos-server:v3.0.3 -o nacos.tar
docker load -i nacos.tar
离线环境部署时这个操作非常实用。
选3.x还有一个理由:Nacos 2.x的控制台用的是老技术栈,3.0重写之后,页面响应速度和操作流畅度提升肉眼可见。更重要的是3.x对配置中心的持久化模块做了重构,配置存储不再只绑定MySQL与内嵌Derby,后续扩展数据库会方便很多。
1.2 端口规划与防火墙策略
Nacos服务端口是规划的重中之重,这张表建议存一下:
| 端口 | 用途 | 说明 |
|---|---|---|
| 8848 | 主端口,HTTP/控制台/API | 必开 |
| 9848 | 客户端gRPC端口,主端口+1000 | 必开 |
| 9849 | 服务端gRPC端口,主端口+1001 | 集群模式下节点同步用 |
| 7848 | 节点间通信端口 | 集群模式下需要 |
很多人只开放8848,服务也注册进去了,但后续客户端频繁报“Client not connected”,或者健康检查失败。原因就是9848没开放:客户端通过8848拿到的偏移端口是9848,连不上gRPC长连接,整个注册就处于假死状态。
如果你是容器部署,docker run或compose里要把8848、9848、9849三个端口都映射出来。生产环境如果有安全组,务必把这三个都放行。这个细节放在第一位讲,因为它最隐蔽,最容易排查半天找不到原因。
1.3 数据存储方案先定下来
Nacos有内嵌Derby和外部数据库两种存储方式。单机开发时,不配外部库也能跑,数据存在容器里;但容器一删,配置和注册数据全没了,这个代价有点大。所以我的建议是:开发环境图省事可以先挂载数据目录,一旦数据要长期留存,或者要做集群,就必须接外部MySQL。
而且Nacos集群有一个硬性要求:所有节点连接同一个外部数据库,绝不能每个节点用自己的Derby,否则节点间数据根本对不上。这个问题在我讲到集群章节时会再次强调。
数据目录挂载很重要:
bash复制-v /opt/nacos/logs:/home/nacos/logs
-v /opt/nacos/data:/home/nacos/data
日志和数据都持久化到宿主机,容器重建不影响历史数据。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Docker环境准备:别让Docker本身卡住你
2.1 Linux环境下的Docker安装
如果是Linux服务器,安装Docker一路默认即可:
bash复制sudo apt update
sudo apt install -y docker.io docker-compose
sudo systemctl enable docker
sudo systemctl start docker
docker version
CentOS/RHEL系就用dnf install docker-ce。装完别急着跑容器,先看一眼docker version,确认客户端和服务端都在,再往下走。
还有镜像拉取速度问题。默认仓库在部分网络环境下拉Nacos镜像很慢,给Docker配置镜像加速器,编辑/etc/docker/daemon.json:
json复制{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
改完执行systemctl daemon-reload && systemctl restart docker。这个配置在国内大多数场景都够用,而且只影响镜像拉取,不影响容器运行。
2.2 Windows/Mac的Docker Desktop与WSL2
在Windows上很多人卡在Docker Desktop起不来,最常见的是Virtualization support wasn't detected这类报错。这类问题大概率是下面三个原因之一:
- BIOS里虚拟化没开:重启进BIOS,找到Intel VT-x或者AMD-V,设置为Enabled
- Windows功能里Hyper-V和“虚拟机平台”没启用:在“启用或关闭Windows功能”里勾选
- WSL2内核版本太老:安装最新版的WSL2 Linux内核更新包
Docker Desktop设置里,把“Use WSL 2 based engine”打开。这种方式比Hyper-V模式更轻量,容器文件存储在VHDX虚拟磁盘里,默认放在C盘,吃紧的话可以在设置里把磁盘镜像位置改到D盘或E盘。改完Docker Desktop会重新导入WSL发行版镜像,第一次启动稍慢,属于正常现象。
有些老版本还会在Windows上报Failed to connect to the Docker API at npipe:////./pipe/dockerDesktopLinuxEngine,出现这类错误通常是Docker Desktop的后台服务卡死了,设置里重启一下,或者退出重新打开基本能解决。我自己的经验是:Windows下跑Nacos,先确认右下角图标从starting变成running再继续,否则后面的端口映射、目录挂载全都白搭。
2.3 检查网络与端口是否已被占用
启动Nacos前先确认8848、9848没有被占用:
bash复制# Linux
sudo lsof -i:8848
# Windows
netstat -ano | findstr 8848
如果端口被占用,被占用的一方也可能是之前的Nacos容器没删干净。我遇到过docker ps看不到容器,但端口还是被docker-proxy占着的情况,这时用docker ps -a看一眼残留容器,确认无用就docker rm。总之,端口问题在前面解决掉,后面启动Nacos会省很多时间。
3. 单机模式部署:一条docker run跑起来
3.1 最小化启动命令
先给最简命令,让Nacos先跑起来,再讲参数:
bash复制docker run -d \
--name nacos-server \
--restart=always \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
-e MODE=standalone \
-e NACOS_AUTH_ENABLE=true \
-v /opt/nacos/logs:/home/nacos/logs \
-v /opt/nacos/data:/home/nacos/data \
nacos/nacos-server:v3.0.3
启动后等待30秒左右,查看日志:
bash复制docker logs -f nacos-server
看到“Nacos started successfully”就说明起来了。访问http://localhost:8848/nacos,默认账号密码nacos/nacos。
这里有一个容易踩的坑:如果开启鉴权(NACOS_AUTH_ENABLE=true)但没有设置NACOS_AUTH_TOKEN等密钥,Nacos 3.x某些版本会启动报错或警告,建议一次性把鉴权参数配齐。后面3.3节会讲怎么配一个真正的密钥。
3.2 逐条拆解关键参数
MODE=standalone:单机模式。不带这个参数默认是cluster,少了集群配置,容器启动后会无限尝试找集群节点,最终起不来。
-p 8848:8848:主端口。Nacos 3.x控制台路径带/nacos。
-p 9848:9848和-p 9849:9849:gRPC端口。3.x的客户端和服务端、服务端之间的通信主要走gRPC,这两个端口不映射,等于Nacos是个半残状态。
-v 数据目录挂载:防止容器重建数据丢失。注意挂载目录在宿主机上要有写权限,否则容器里创建文件失败。如果发现日志不停报权限问题,先chmod,或者把目录属主改成当前用户。
--restart=always:让Docker守护进程在容器退出时自动拉起,机器重启后也能自动恢复。生产环境的容器我一般都会加这个参数,省得半夜服务挂了没人拉起来。
3.3 开启鉴权并配置密钥
开发环境你可以先不开鉴权,但如果这台Nacos能被局域网其他人访问,或者后面要放到公网,必须开。Nacos 3.x内置鉴权参数如下:
bash复制docker run -d \
--name nacos-server \
-p 8848:8848 -p 9848:9848 -p 9849:9849 \
-e MODE=standalone \
-e NACOS_AUTH_ENABLE=true \
-e NACOS_AUTH_TOKEN=<你的Base64密钥> \
-e NACOS_AUTH_IDENTITY_KEY=serverIdentity \
-e NACOS_AUTH_IDENTITY_VALUE=<自定义身份值> \
-v /opt/nacos/logs:/home/nacos/logs \
-v /opt/nacos/data:/home/nacos/data \
nacos/nacos-server:v3.0.3
生成密钥可以用:
bash复制openssl rand -base64 32
NACOS_AUTH_TOKEN要求至少32字节,并且最好使用Base64编码后的字符串。别用123456这种弱密钥,否则别人拿到你的Nacos地址,改一下密码就能接管所有配置。3.x也提供了新的鉴权插件体系,生产环境可以按官方文档接入,但内置鉴权模式部署起来最直接,当前仍然兼容。
3.4 验证部署是否成功
光访问控制台还不够,本地验证一下注册和发现是否正常:
bash复制# 注册一个临时实例
curl -X POST "http://localhost:8848/nacos/v1/ns/instance?serviceName=test-service&ip=127.0.0.1&port=8080"
# 查询该服务下的实例
curl -X GET "http://localhost:8848/nacos/v1/ns/instance/list?serviceName=test-service"
能查到刚才注册的实例,说明服务发现链路是通的。配置发布可以到控制台新建一个配置,或者用curl发布:
bash复制curl -X POST "http://localhost:8848/nacos/v1/cs/configs" \
-d "dataId=config-test.yml&group=DEFAULT_GROUP&content=name: nacos"
查询回去能拿到内容,配置链路也通了。我一般会多测这一步,因为有时候控制台能打开,但gRPC端口有问题,配置发布成功却推送不到客户端,这种问题只有实测过才知道。
4. 把数据持久化到MySQL:不配置等于白部署
4.1 为什么要接MySQL
Nacos默认用内嵌Derby存储配置和注册数据,适合单机和练手。但生产环境至少两个理由必须换MySQL。
第一,数据安全。容器重建、宿主机宕机,挂载数据目录虽然能保数据,但损坏风险比专业数据库高得多。第二,集群一致性。Nacos集群要求所有节点连同一个数据库,配置数据集中管理,节点之间只同步服务实例和健康状态,从这个意义上讲,MySQL是集群模式的硬前提。
如果你的MySQL是8.x,Nacos 3.x支持得挺好;5.7也可以。MySQL本身用Docker部署,参考:
bash复制docker run -d --name mysql-8 \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=root123 \
-e MYSQL_DATABASE=nacos_config \
mysql:8.0
4.2 初始化数据库脚本
Nacos的MySQL脚本在镜像里有,如果容器没起来,可以用一个临时容器拷出来:
bash复制# 先起一个临时容器,把脚本拷到宿主机
docker create --name nacos-tmp nacos/nacos-server:v3.0.3
docker cp nacos-tmp:/home/nacos/conf/ /tmp/nacos-conf
docker rm nacos-tmp
脚本文件是/tmp/nacos-conf/nacos-mysql.sql。在MySQL里执行:
bash复制mysql -h127.0.0.1 -uroot -proot123 nacos_config < /tmp/nacos-conf/nacos-mysql.sql
执行完登录MySQL检查一下表:
bash复制mysql -h127.0.0.1 -uroot -proot123 nacos_config -e "show tables;"
应该能看到config_info、config_info_tag、his_config_info、service_info、users等表。这些表对应配置中心和服务发现的持久化数据。如果脚本执行完一张表都没有,大概率是没进对数据库,或者执行时连错了MySQL实例。
4.3 数据库版启动命令
接好库之后,用下面的命令启动Nacos:
bash复制docker run -d \
--name nacos-server \
-p 8848:8848 -p 9848:9848 -p 9849:9849 \
-e MODE=standalone \
-e NACOS_AUTH_ENABLE=true \
-e NACOS_AUTH_TOKEN=<你的Base64密钥> \
-e NACOS_AUTH_IDENTITY_KEY=serverIdentity \
-e NACOS_AUTH_IDENTITY_VALUE=<自定义身份值> \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=127.0.0.1 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=nacos \
-e MYSQL_SERVICE_PASSWORD=nacos123 \
-e MYSQL_SERVICE_DB_PARAM="characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC" \
nacos/nacos-server:v3.0.3
几个说明:
- 如果你的Nacos容器和MySQL容器跑在同一台宿主机,MYSQL_SERVICE_HOST不能写localhost,要写宿主机IP,或者让两个容器在同一个Docker网络里用容器名互相访问。因为容器内的localhost是容器自己。
- MYSQL_SERVICE_USER建议单独建一个nacos账号,不要用root,权限最小化,这是数据库安全的基本习惯。
- allowPublicKeyRetrieval=true这个参数是MySQL 8.x的caching_sha2_password认证方式需要的,不加的话连接会报Public Key Retrieval is not allowed。
- SPRING_DATASOURCE_PLATFORM=mysql要显式设置。有些版本不设置会回退到Derby,你会看到明明配了MySQL,但控制台数据还是存到了容器内。
4.4 验证数据落库
启动后,到控制台新建一个配置,然后去MySQL里查:
sql复制SELECT data_id, group_id, content FROM config_info;
能看到刚创建的配置记录,说明持久化成功。查不到就回来看容器日志docker logs nacos-server,重点看有没有数据库连接失败、表不存在这类错误。这一步验证很关键,别等数据丢了再想起来检查。
5. 集群模式部署:3节点Nacos集群实战
5.1 集群模式和单机模式的差别
Nacos集群最少3个节点,目的是高可用。一个节点挂了,其他节点依然能提供注册和配置服务,客户端通过负载均衡访问任意节点。集群模式下有几个硬性要求:
- 所有节点连接同一个MySQL数据库,数据统一
- 节点之间通过gRPC和raft协议通信,节点间网络要通
- 所有节点端口要一致且开放8848/9848/9849/7848
- 不建议只搭2节点,因为raft协议需要多数派才能选主,2节点挂1个可能选票不足
在Docker里,集群节点可以用容器名互相访问,这样不需要知道每个宿主机的IP。前提是它们加入同一个Docker网络,并且设置了hostname。
5.2 Docker Compose一键部署集群
创建文件docker-compose-nacos.yml:
yaml复制version: "3.8"
services:
nacos1:
image: nacos/nacos-server:v3.0.3
container_name: nacos1
hostname: nacos1
restart: always
network_mode: host
environment:
- MODE=cluster
- NACOS_SERVERS=nacos1:8848,nacos2:8848,nacos3:8848
- NACOS_SERVER_PORT=8848
- NACOS_AUTH_ENABLE=true
- NACOS_AUTH_TOKEN=<你的Base64密钥>
- NACOS_AUTH_IDENTITY_KEY=serverIdentity
- NACOS_AUTH_IDENTITY_VALUE=<自定义身份值>
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=192.168.1.100
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos123
volumes:
- /opt/nacos1/logs:/home/nacos/logs
- /opt/nacos1/data:/home/nacos/data
nacos2:
image: nacos/nacos-server:v3.0.3
container_name: nacos2
hostname: nacos2
restart: always
network_mode: host
environment:
- MODE=cluster
- NACOS_SERVERS=nacos1:8848,nacos2:8848,nacos3:8848
- NACOS_SERVER_PORT=8848
- NACOS_AUTH_ENABLE=true
- NACOS_AUTH_TOKEN=<你的Base64密钥>
- NACOS_AUTH_IDENTITY_KEY=serverIdentity
- NACOS_AUTH_IDENTITY_VALUE=<自定义身份值>
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=192.168.1.100
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos123
volumes:
- /opt/nacos2/logs:/home/nacos/logs
- /opt/nacos2/data:/home/nacos/data
nacos3:
image: nacos/nacos-server:v3.0.3
container_name: nacos3
hostname: nacos3
restart: always
network_mode: host
environment:
- MODE=cluster
- NACOS_SERVERS=nacos1:8848,nacos2:8848,nacos3:8848
- NACOS_SERVER_PORT=8848
- NACOS_AUTH_ENABLE=true
- NACOS_AUTH_TOKEN=<你的Base64密钥>
- NACOS_AUTH_IDENTITY_KEY=serverIdentity
- NACOS_AUTH_IDENTITY_VALUE=<自定义身份值>
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=192.168.1.100
-
