摘要 :在上篇文章中(从"裸奔"到"装甲":基于 Docker + Spring Boot 的企业级多环境安全架构实战),我们实现了 Spring Boot 配置的"外部化"。但在微服务架构下,分散在各个服务器上的
.env文件依然难以维护。本文将带你完成从"静态环境变量"到"动态配置中心"的跃迁,使用 Nacos 统一管理所有环境配置,并实现配置热更新。
前言:当 .env文件不再够用时
在上一个方案中,我们通过 Docker 的 env_file注入了 .env文件。这在单体应用中非常完美,但当面临以下场景时,它会显得力不从心:
-
配置散落 :10 个服务就有 10 个
.env文件,分布在 10 台服务器上。 -
重启代价 :修改一个 Redis 地址,必须
docker restart。 -
无版本管理:谁改了配置?什么时候改的?回滚怎么办?
-
安全性焦虑:虽然没进 Git,但运维手里还是握着一堆密码。
Nacos 的出现就是为了解决这些问题。它不仅是注册中心,更是配置中心。
第一章:新架构全景图
我们先来看一下引入 Nacos 后的架构变化。

1.1 架构对比

| 维度 | Docker Env 方案 | Nacos 方案 |
|---|---|---|
| 存储位置 | 服务器文件 (.env) | Nacos Server 数据库 |
| 更新机制 | 重启容器 | 实时推送 / 热更新 |
| 管理方式 | 分散管理 | 统一 Web 控制台 |
| 版本控制 | 无 | 自带历史版本与回滚 |
| 适用场景 | 单体应用 | 微服务 / 分布式 |
1.2 数据流
+-------------------+ 推送配置 +-------------------+
| Nacos Console | -----------> | Nacos Server |
+-------------------+ +---------+---------+
|
| 监听变更 (Long Polling)
v
+-------------------+
| Spring Boot App |
| (Nacos Config Client)|
+-------------------+
第二章:Nacos 环境准备
2.1 使用 1Panel 快速部署 Nacos
如果你在用 1Panel,部署 Nacos 非常简单。
-
进入 应用商店 -> 搜索 Nacos。
-
选择 单机模式(Standalone)。
-
设置端口映射(例如
8848)。 -
启动。
2.2 初始化命名空间 (Namespace)
为了区分环境,我们在 Nacos 中创建命名空间。
| Namespace ID | Name | 说明 |
|---|---|---|
dev |
开发环境 | 开发同学使用 |
test |
测试环境 | 测试同学使用 |
prod |
生产环境 | 线上环境 |
第三章:Spring Boot 接入 Nacos
这是最核心的代码改造环节。

3.1 依赖变更 (pom.xml)
移除或保留原有的 Spring Cloud Alibaba 依赖。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
3.2 配置文件大挪移
我们要把原来写在 application-dev.yml里的东西,搬到 Nacos 里。
本地只保留一个 bootstrap.yml(优先级最高,用于连接 Nacos)。
# bootstrap.yml
spring:
application:
name: shiyuan-admin
cloud:
nacos:
discovery:
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848}
config:
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848}
file-extension: yaml
# 关键:指定命名空间(dev/test/prod)
namespace: ${NACOS_NAMESPACE:dev}
# 配置分组
group: DEFAULT_GROUP
# 支持动态刷新
refresh-enabled: true
3.3 Nacos 中的配置内容
在 Nacos 控制台 dev命名空间下,创建配置 shiyuan-admin.yaml。
Data ID : shiyuan-admin.yaml
Group : DEFAULT_GROUP
配置内容 (这就是你原来的 application-dev.yml去掉占位符后的版本,但密码等敏感信息依然用占位符,或者直接用真实值放在 Nacos 里更安全):
spring:
datasource:
dynamic:
datasource:
master:
url: jdbc:mysql://${DB_HOST}:3306/${DB_NAME}?useSSL=false
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
data:
redis:
host: ${REDIS_HOST}
password: ${REDIS_PASSWORD}
# 邮件
mail:
pass: ${MAIL_PASS}
# 短信
sms:
blends:
aliyun:
access-key-id: ${SMS_ALI_ACCESS_KEY}
access-key-secret: ${SMS_ALI_SECRET}
注意 :你会发现这里还是有 ${}。这是因为 Nacos 也支持从环境变量读取(推荐),或者你也可以直接在 Nacos 里写死值。
第四章:Docker 与 Nacos 的结合(关键)

现在,我们不再需要把大量的配置塞进 .env,只需要告诉 Spring Boot Nacos 在哪里。
4.1 新的 .env文件
.env文件变得非常精简,只负责"引导"应用。
# ================== 基础 ==================
CONTAINER_NAME=shiyuan-admin
CODE_DIR=/opt/apps/shiyuan-admin/target
JAVA_APP_PORT=9113
# ================== Nacos 环境 ==================
NACOS_SERVER_ADDR=172.17.0.1:8848 # Docker 网桥地址
NACOS_NAMESPACE=dev
# ================== 敏感信息(仅作为兜底) ==================
# 如果 Nacos 里的配置也用了变量,这里需要提供
DB_PASSWORD=YourStrongPassword
REDIS_PASSWORD=RedisPass
4.2 新的 docker-compose.yml
networks:
1panel-network:
external: true
services:
java-app:
container_name: ${CONTAINER_NAME}
image: bitnami/java:17
command: bash /run.sh
env_file:
- .env # 只注入 Nacos 地址和少量敏感变量
environment:
- TZ=Asia/Shanghai
# 这里不再需要 SPRING_PROFILES_ACTIVE,由 Nacos Namespace 控制
networks:
- 1panel-network
ports:
- ${HOST_IP}:${PANEL_APP_PORT_HTTP}:${JAVA_APP_PORT}
restart: on-failure:5
volumes:
- ${CODE_DIR}:/app
- ./run.sh:/run.sh
working_dir: /app
4.3 改造 run.sh(支持 JVM 参数从 Nacos 读取)
虽然配置在 Nacos,但 JVM 参数通常还是在启动时确定。
#!/bin/bash
set -e
cd /app
echo "==> Connecting to Nacos: $NACOS_SERVER_ADDR"
echo "==> Namespace: $NACOS_NAMESPACE"
exec java \
-Xms512m \
-Xmx1024m \
-XX:+UseG1GC \
-XX:+HeapDumpOnOutOfMemoryError \
-Dspring.cloud.nacos.config.namespace=${NACOS_NAMESPACE} \
-Dspring.cloud.nacos.server-addr=${NACOS_SERVER_ADDR} \
-jar shiyuan-admin.jar
第五章:实现"配置热更新"(@RefreshScope)
这是 Nacos 最诱人的功能。
5.1 代码示例
假设你有一个读取 Redis 配置的 Bean:
@RestController
@RequestMapping("/config")
@RefreshScope // 核心注解:开启配置刷新
public class ConfigController {
@Value("${spring.data.redis.host}")
private String redisHost;
@GetMapping("/redis-host")
public String getRedisHost() {
return "Current Redis Host: " + redisHost;
}
}
5.2 操作流程
-
修改 Nacos 中
shiyuan-admin.yaml的spring.data.redis.host。 -
点击 发布。
-
无需重启应用 ,再次访问
/config/redis-host,发现值已经变了。
第六章:Nacos 鉴权与安全
Nacos 本身也需要安全加固。
6.1 开启鉴权
在 1Panel 部署 Nacos 时,务必开启鉴权(或手动修改 application.properties):
nacos.core.auth.enabled=true
nacos.core.auth.system.type=nacos
6.2 配置 Docker 认证
如果 Nacos 开了鉴权,.env需要增加:
NACOS_USERNAME=nacos
NACOS_PASSWORD=YourNacosPassword
并在 bootstrap.yml中配置:
spring:
cloud:
nacos:
username: ${NACOS_USERNAME}
password: ${NACOS_PASSWORD}
第七章:迁移过程中的坑与解决方案

坑 1:配置加载顺序混乱
现象:本地配置覆盖了 Nacos 配置。
解决:记住 Spring Boot 配置优先级(从高到低):
-
Command Line Arguments (
--server.port=8081) -
JNDI attributes
-
Java System Properties (
-Dproperty=value) -
OS Environment Variables (Docker env)
-
Nacos Config
-
application-{profile}.yml -
application.yml -
@PropertySource
经验 :不要把同样的配置写在 application.yml里,否则会覆盖 Nacos。
坑 2:Nacos 连不上
现象 :java.net.ConnectException: Connection refused
解决:
-
检查
NACOS_SERVER_ADDR是否是 Docker 容器能访问到的地址。 -
如果是 1Panel,
127.0.0.1可能不行,要用宿主机的局域网 IP 或 Docker 网桥 IP(如172.17.0.1)。
坑 3:配置回滚
操作:在 Nacos 控制台 -> 配置管理 -> 历史版本 -> 选择版本 -> 回滚。
第八章:最终的安全架构评估
经过这次改造,我们的安全等级再次提升。
| 资产 | 存放位置 | 安全性 |
|---|---|---|
| 代码 | Git | ⭐⭐⭐⭐⭐ (无密码) |
| Jar 包 | Docker Image | ⭐⭐⭐⭐⭐ (无密码) |
| 引导配置 | .env(Server) |
⭐⭐⭐⭐ (仅 Nacos 地址) |
| 业务配置 | Nacos Server | ⭐⭐⭐⭐⭐ (有权限控制、审计) |
| 数据库 | 内网 VPC | ⭐⭐⭐⭐⭐ |
结语
从最初的"密码满天飞",到 Docker 环境变量隔离,再到 Nacos 统一配置中心,我们不仅解决了技术问题,更完成了一次工程思维的升级。
现在的架构优势在于:
-
运维友好:运维只管 Nacos,不用碰代码。
-
开发友好:开发只看 Git,不用管密码。
-
应急高效:改配置不用重启,秒级生效。
-
审计合规:谁改了什么,一清二楚。
如果你的项目正在从单体走向微服务,或者正在为配置管理头疼,强烈建议你试试这套方案。