☰
Docker部署Nacos v3.1.1:单机、集群与MySQL持久化实战
2026/10/10 3:20:58 网站建设 项目流程

平时做微服务改造,服务注册与配置中心是绕不开的一环。Nacos 作为这个领域用得最多的组件之一,最新已经迭代到 v3.1.1。这篇文章就记录一下我这次用 Docker 部署 Nacos Server v3.1.1 的完整过程,包括单机快速拉起、生产环境的数据持久化、对接 MySQL、集群模式编排,以及我在实际排障中踩过的几个坑。

我默认看这篇文章的你已经具备最基础的 Docker 操作能力,知道docker run、docker compose大概是怎么回事。如果你连 Docker 都还没装好,第 1 章的前半部分会先把环境给捋顺。想直接抄作业的,可以直接跳到第 2 章的单机部署部分。

1. 部署前必须想清楚的三件事

1.1 为什么选择 Nacos v3.1.1

在很多存量项目里,Nacos 2.x 是绝对的主力版本。这次我之所以直接上 v3.1.1,核心原因是新项目从零搭建,没有历史包袱,没必要再去迁就旧版本。v3.x 系列在整体架构上做了不少调整,给我的直观感受是启动速度更快、内存占用比 2.x 更可控,API 层也做了收敛,官方文档说得比较明白:如果是从 2.x 升级上来的,一定要先读升级说明,因为一些配置项的命名和默认行为有变化。

另外一点是,v3.x 的 Docker 镜像做得更干净,默认配置已经能覆盖大部分场景,不需要像以前那样启动后再手动改一堆配置文件。配合环境变量就能完成模式和数据库的切换,这对容器化部署来说非常友好。如果你所在的团队还在用 2.x 且运行稳定,我不建议盲目追新;但如果是新项目,直接上 v3.1.1 没有太大风险。

1.2 环境检查:Docker 得先稳稳跑起来

很多人部署失败其实不是 Nacos 的问题,而是 Docker 环境本身就没就绪。我在 Windows 上用的是 Docker Desktop,最常遇到的是启动时报virtualisation support wasn't detected,这种十有八九是 BIOS 里的虚拟化没打开,或者 WSL2 内核没更新。去控制面板启用“虚拟机平台”和 WSL,然后执行一次wsl --update,基本就能解决。

Linux 服务器上更常见的是权限问题,报错长这样:permission denied while trying to connect to the docker api socket。这不是 Docker 坏了,而是你当前用户不在 docker 用户组里。执行下面两条命令然后重新登录一次就行:

sudo usermod -aG docker $USER newgrp docker

装好之后,用这两个命令确认状态:

docker version docker info

如果docker version能正常输出 Server 端信息,说明 Docker 后台服务在跑;如果只有 Client 信息,那就要先启动服务,Linux 下通常是sudo systemctl start docker。

1.3 端口与目录规划

部署前把端口和目录规划好,能省掉后面一大堆麻烦。Nacos 服务本身涉及四个关键端口,我整理成一个表方便对照:

端口用途说明
8848HTTP 主端口控制台、配置管理、服务注册的 HTTP 接口
9848客户端 gRPC 端口新版客户端必须靠这个端口通信
9849服务间 gRPC 端口集群节点之间的通信
7848集群成员信息端口仅集群模式使用,单机不占用

注意,9848 和 9849 并不是你手动指定的端口,而是 Nacos 根据 8848 自动偏移算出来的。也就是说你把 8848 映射到宿主机的 8080,那 gRPC 用的就是 8081 和 8082,这个偏移规则要看清楚,不然很容易出现“页面能开、但客户端死活连不上”的怪问题。

目录规划方面,我习惯把所有容器的数据集中放在一个目录下,比如/opt/docker-data/nacos,下面再分logs、data、conf三个子目录。这样备份、迁移、清理都很清晰,也不会因为容器重建把数据搞丢。

2. 单机模式快速拉起 Nacos

2.1 镜像拉取与 tag 选择

镜像直接从官方仓库拉:

docker pull nacos/nacos-server:v3.1.1

这里有一个细节:我从来不直接用latest标签。原因很简单,latest指向的版本会随官方发布变化,可能今天部署的是 3.1.1,过几个月同一镜像 tag 内容就变了,脚本重跑很可能出现版本漂移。用完整版本号v3.1.1拉取,保证锁定的就是目标版本,可复现性最好。拉取的时候如果发现速度特别慢,老办法是给 Docker daemon 配置镜像源加速,这个在 Docker Desktop 的 Settings -> Docker Engine 里直接改 JSON 就行,Linux 则要改/etc/docker/daemon.json。

2.2 一条命令启动容器

单机开发环境最简启动方式是这样的:

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/docker-data/nacos/logs:/home/nacos/logs \ -v /opt/docker-data/nacos/data:/home/nacos/data \ nacos/nacos-server:v3.1.1

逐个解释几个关键点:

  • MODE=standalone:明确指定单机模式。不指定的话,镜像内的默认启动脚本可能按集群模式去找 peer 节点,导致启动失败。
  • NACOS_AUTH_ENABLE=true:开启控制台登录鉴权。现在网络环境越来越复杂,如果不开启鉴权,8848 端口暴露到外网后,配置信息基本等于裸奔。开发环境也建议开着,养成习惯。
  • --restart always:容器意外退出时自动拉起。这个在服务器重启的场景下非常有用,相当于给了 Nacos 一层基础守护。
  • 数据卷挂载:把容器内的logs和data目录映射到宿主机,这是防止“容器一删,数据全无”的关键操作,后面专门讲。

启动完成后,用docker ps看容器状态,正常应该是Up且没有Restarting的标志。

2.3 首次访问与默认账号

浏览器访问:

http://localhost:8848/nacos

首次登录使用默认账号nacos / nacos。这里我强烈建议登录后立刻去控制台改掉默认密码,或者通过环境变量在启动时就自定义密码。v3.x 对安全相关的默认行为做了收紧,但默认账号还是存在,你不动它,别人就可能动它。

登录进入控制台之后,先到“命名空间”里看一眼,默认会有一个public命名空间,这是 Nacos 内置的保留空间。新项目的配置和服务尽量不要都塞在public里,最好按环境和业务划分命名空间,不然以后配置多了,管理起来会非常痛苦。

3. 数据持久化与外部数据库接入

3.1 不要裸奔:数据卷挂载的真正原因

Docker 容器的文件系统是临时的,容器被docker rm删除之后,容器内所有改动都会消失。就算你只是升级镜像重新创建容器,如果不挂载数据卷,原有的配置和数据也全没了,这是一个新手上路最容易踩的坑。

我在单机模式里挂载了两个目录:

  • /home/nacos/logs:运行日志,排障时查看docker logs也能看到,但挂载到宿主机后检索更方便。
  • /home/nacos/data:Nacos 内嵌存储的数据文件,单机模式使用内嵌存储时,服务实例、配置快照都在这里。

挂载后,哪怕容器被删了,重新用同样的参数再docker run一次,数据依然还在。用生活化的比喻来说,这相当于把“笔记本”从容器里拿到了你手里,容器只是临时用一下笔而已。

3.2 对接 MySQL:从单机走向生产的关键

单机模式默认的内嵌存储只适合本地开发和功能验证。一旦涉及多人协作、配置更新频繁、或者要上集群,就必须切换到 MySQL 外部存储。

首先在 MySQL 里创建 Nacos 专用的数据库和账号:

CREATE DATABASE nacos_config DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'nacos'@'%' IDENTIFIED BY 'your_password'; GRANT ALL PRIVILEGES ON nacos_config.* TO 'nacos'@'%'; FLUSH PRIVILEGES;

然后初始化表结构。Nacos 镜像内自带初始化脚本,通常在/home/nacos/conf/目录下,文件名为mysql-schema.sql之类的。你可以先把容器跑起来,再从里面拷贝出来执行:

docker cp nacos-server:/home/nacos/conf/mysql-schema.sql ./mysql-schema.sql mysql -h你的mysql地址 -unacos -p nacos_config < mysql-schema.sql

接下来用带 MySQL 参数的方式重新启动容器:

docker run -d \ --name nacos-server \ -p 8848:8848 \ -p 9848:9848 \ -p 9849:9849 \ -e MODE=standalone \ -e SPRING_DATASOURCE_PLATFORM=mysql \ -e MYSQL_SERVICE_HOST=你的数据库地址 \ -e MYSQL_SERVICE_DB_NAME=nacos_config \ -e MYSQL_SERVICE_USER=nacos \ -e MYSQL_SERVICE_PASSWORD=你的密码 \ -e MYSQL_SERVICE_PORT=3306 \ -e NACOS_AUTH_ENABLE=true \ -v /opt/docker-data/nacos/logs:/home/nacos/logs \ nacos/nacos-server:v3.1.1

注意SPRING_DATASOURCE_PLATFORM=mysql这个变量不能漏。有些教程在里面写的是MYSQL_SERVICE_PORT=3306,但忘了声明平台类型,结果 Nacos 还是用内嵌存储跑起来了,数据没有真正进 MySQL,这种“假对接”比较隐蔽,日志不会报错,但看数据库里的表你会发现全是空的。

3.3 挂载自定义配置文件

虽然大部分配置都能用环境变量覆盖,但总有特殊需求。我的做法是准备一份自定义配置文件,比如custom.properties,把它挂载到容器的/home/nacos/conf/custom.properties路径下。Nacos 启动时如果检测到该文件,会把它作为附加配置加载。

这个机制适合放那些环境变量不好表达的配置,比如某些自定义的鉴权密钥轮换策略、日志级别细调等。要注意的是,挂载配置文件时要确认容器内路径准确,不同版本的镜像路径可能有偏差,最稳妥的办法是先进容器看一眼ls /home/nacos/conf/再决定挂载目标。

4. 集群部署实战:docker compose 编排

4.1 集群规划与选型思路

单机模式再好,也有单点风险。一旦容器所在宿主机宕机,注册中心就挂了,所有依赖它的服务都会开始报错。生产环境至少要三个节点组成集群,这样可以保证在多数派可用的情况下依然正常对外服务。

集群模式有两个硬性前提:

  • 必须使用外部 MySQL,不能再用内嵌存储;
  • 所有节点必须能通过网络互相访问,而且 8848、9848、9849、7848 端口都要打通。

我采用的方案是三个 Nacos 容器 + 一个 MySQL 实例,全部用 docker compose 编排在同一台机器上。这种部署方式适合资源有限的中小型项目,真正大规模生产环境则建议把 MySQL 独立出来,甚至可以每个 Nacos 节点使用独立的数据库实例。

4.2 compose 编排文件详解

下面是完整的docker-compose.yml:

version: "3.8" services: nacos1: image: nacos/nacos-server:v3.1.1 container_name: nacos1 environment: - MODE=cluster - NACOS_SERVERS=nacos1:8848,nacos2:8848,nacos3:8848 - SPRING_DATASOURCE_PLATFORM=mysql - MYSQL_SERVICE_HOST=mysql - MYSQL_SERVICE_DB_NAME=nacos_config - MYSQL_SERVICE_USER=nacos - MYSQL_SERVICE_PASSWORD=your_password - MYSQL_SERVICE_PORT=3306 - NACOS_AUTH_ENABLE=true ports: - "8848:8848" - "9848:9848" - "9849:9849" volumes: - /opt/docker-data/nacos1/logs:/home/nacos/logs restart: always depends_on: - mysql nacos2: image: nacos/nacos-server:v3.1.1 container_name: nacos2 environment: - MODE=cluster - NACOS_SERVERS=nacos1:8848,nacos2:8848,nacos3:8848 - SPRING_DATASOURCE_PLATFORM=mysql - MYSQL_SERVICE_HOST=mysql - MYSQL_SERVICE_DB_NAME=nacos_config - MYSQL_SERVICE_USER=nacos - MYSQL_SERVICE_PASSWORD=your_password - MYSQL_SERVICE_PORT=3306 - NACOS_AUTH_ENABLE=true ports: - "8849:8848" - "9850:9848" - "9851:9849" volumes: - /opt/docker-data/nacos2/logs:/home/nacos/logs restart: always depends_on: - mysql nacos3: image: nacos/nacos-server:v3.1.1 container_name: nacos3 environment: - MODE=cluster - NACOS_SERVERS=nacos1:8848,nacos2:8848,nacos3:8848 - SPRING_DATASOURCE_PLATFORM=mysql - MYSQL_SERVICE_HOST=mysql - MYSQL_SERVICE_DB_NAME=nacos_config - MYSQL_SERVICE_USER=nacos - MYSQL_SERVICE_PASSWORD=your_password - MYSQL_SERVICE_PORT=3306 - NACOS_AUTH_ENABLE=true ports: - "8850:8848" - "9852:9848" - "9853:9849" volumes: - /opt/docker-data/nacos3/logs:/home/nacos/logs restart: always depends_on: - mysql mysql: image: mysql:8.0 container_name: nacos-mysql environment: - MYSQL_ROOT_PASSWORD=root_password - MYSQL_DATABASE=nacos_config - MYSQL_USER=nacos - MYSQL_PASSWORD=your_password ports: - "3306:3306" volumes: - /opt/docker-data/nacos-mysql:/var/lib/mysql command: - --default-authentication-plugin=mysql_native_password restart: always

几个要点说明:

  • NACOS_SERVERS里填的是三个容器的服务名加 8848 端口,compose 网络内会做 DNS 解析,不需要写宿主机 IP。
  • 第二个和第三个节点的宿主机端口故意改成了不同的映射,避免 host 端口冲突。但是容器内的8848保持不变,NACOS_SERVERS里也始终使用容器内端口。
  • depends_on只能保证 MySQL 容器先启动,不能保证 MySQL 已经完全 ready。实际部署时,如果 Nacos 启动报数据库连接失败,等十几秒再重启一次 Nacos 容器即可。
  • MySQL 的--default-authentication-plugin=mysql_native_password参数是为了兼容一些老客户端,如果你的客户端都是新的,这个参数可以去掉。

启动命令:

docker compose up -d

4.3 集群验证

三个节点都起来之后,进入管理后台的“集群管理 -> 节点列表”,应该能看到三个节点都处于UP状态。确认方式也可以走 HTTP 接口:

curl http://localhost:8848/nacos/v1/console/health/cluster

返回的 JSON 里有集群的节点列表和每个节点的健康状态。如果某个节点显示DOWN,优先检查该容器日志,常见的原因是节点之间 9848 端口不通或者 MySQL 连接失败。

5. 常见问题与排障实录

5.1 容器启动后反复退出

这是最让人崩溃的场景:docker ps里容器状态是Restarting,每隔几秒就重启一次。

第一时间看日志:

docker logs -f nacos-server

我遇到的几种典型原因和对应处理方式:

  • 内存不足:默认 JVM 参数可能比较大,如果宿主机内存有限,可以加环境变量调小,比如-e JVM_XMS=256m -e JVM_XMX=256m -e JVM_XMN=128m。
  • 端口被占用:宿主机上已有进程占用了 8848、9848 或 9849,改 host 映射端口即可。
  • 数据库连不上:日志里通常有CannotGetJdbcConnectionException之类的字样,确认数据库地址、账号、密码、数据库名是否都对,以及数据库脚本是否已经执行过。

5.2 页面能开,但服务一直注册不上

页面能打开说明 8848 端口是通的,但客户端注册不上,大概率是 gRPC 通信出了问题。客户端 SDK 在向 Nacos 注册时,除了走 8848,还会尝试连接 9848 端口。

如果宿主机防火墙没放行 9848,或者容器端口映射漏了 9848,就会出现“页面看起来一切正常,但服务死活注册不上”的诡异现象。检查一下:

netstat -tlnp | grep 9848

如果是云服务器,还要去安全组里确认 8848 和 9848 都放行了。另外,客户端版本和 Server 版本差太多也可能出现兼容问题,尽量保持客户端版本不落后 Server 版本一个主版本以上。

5.3 权限与内核相关报错

把当前用户加进 docker 组之后,执行docker ps通常就好了,但要注意,修改完用户组必须重新登录会话才生效。如果还是提示没有权限,可能是 Docker daemon 本身没有启动,通过systemctl status docker或 Docker Desktop 的图标状态确认一下。

另外,如果宿主机内核参数过低,Nacos 日志里可能出现max file descriptors或内存映射不足相关的警告。修改/etc/sysctl.conf里的vm.max_map_count,执行sysctl -p让它生效。这个参数在运行大量容器或搜索类中间件时尤其重要,是我的标准预检查项。

6. 日常运维与升级备份

6.1 健康检查与日志检索

部署完之后,不要把docker ps显示Up当成万事大吉。我习惯加一个定期健康检查脚本,直接调接口:

curl -s -o /dev/null -w "%{http_code}" http://localhost:8848/nacos/v1/console/health/readiness

返回200表示就绪。如果你用 Docker compose,还可以在 compose 文件里为 Nacos 服务配置healthcheck,让 Docker 来帮你周期性地探活。

日志查看方面,进容器看日志或者直接看宿主机挂载目录里的文件都可以。排查问题时,我常用的命令是:

docker logs --tail 200 -f nacos-server

6.2 升级与回滚

升级前一定要备份数据,这是铁律。我的步骤是先备份 MySQL 数据库,再备份宿主机上的挂载目录:

mysqldump -h你的mysql地址 -unacos -p nacos_config > nacos_config_backup.sql tar -czvf nacos_data_backup.tar.gz /opt/docker-data/nacos

然后拉取新版本镜像,停旧容器,启动新容器。启动参数保持不变即可。如果新版本行为异常,直接再用旧版本的 tag 重新docker run一次,利用之前备份的目录挂载回去,几十秒就能回滚。这里再次体现出 tag 锁定和目录规划的价值。

6.3 一条备份脚本建议

最后分享一个我一直用的懒人备份脚本,放到 crontab 里定期执行,省心很多:

#!/bin/bash BACKUP_DIR=/backup/nacos DATE=$(date +%Y%m%d%H%M) mysqldump -h127.0.0.1 -unacos -p密码 nacos_config > $BACKUP_DIR/nacos_$DATE.sql tar -czf $BACKUP_DIR/nacos_files_$DATE.tar.gz -C /opt/docker-data/nacos . find $BACKUP_DIR -name "*.sql" -mtime +7 -delete find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

这个脚本做完全量备份之后会自动清理 7 天前的旧备份。说实话,Nacos 这类基础组件的备份容灾,平时没人关注,真正出事的时候才知道备份有多重要。我自己的习惯是:开发环境用单机加数据卷,生产环境用集群加 MySQL,备份策略每周全量、每日增量。这套组合拳打下来,Nacos 这块基本没出过什么需要半夜爬起来解决的状况。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询