Docker+K8s Nacos SpringBoot
In modern microservice architectures, dynamic configuration management across multiple environments (such as dev, test, and prod) is crucial for seamless application lifecycles. Nacos, developed by Alibaba as an open-source configuration and service discovery platform, introduces the concept of Namespaces to isolate configurations within a single instance. Meanwhile, Spring Boot natively supports externalized configuration loading through mechanisms like spring.config.import and profile management. Combining these tools in a Docker and Kubernetes (K8s) ecosystem enables unified, environment-agnostic configuration governance.
This article explores the mapping relationship between Nacos namespaces and Spring Boot native configurations, providing a comprehensive, practical guide for containerized multi-environment deployments.
- Logical Isolation: Every namespace holds a distinct set of configurations, ensuring that resources in different environments do not interfere with one another.
- Multi-tenancy: Ideal for segregating configurations across various business lines, tenants, or deployment stages using the same backend infrastructure.
- Default Namespace: The
publicnamespace serves as the fallback target for any configuration that does not explicitly declare a namespace ID. - Namespace ID: A system-generated UUID. Best practices dictate using this ID rather than the human-readable name in deployment scripts and code to prevent naming collision issues.
Namespace Hierarchical Structure
Namespace
└─ Data ID (Configuration File Name)
└─ Group (Default: DEFAULT_GROUP)
└─ Content (properties / yaml / json)
Spring Boot Configuration Loading Order
When a Spring Boot application boots up, it evaluates and loads configurations in a specific precedence order (from highest to lowest):
- Command Line Arguments (e.g.,
--spring.config.import=nacos:...) application.yml/application.properties(located inclasspath:/,classpath:/config/, or the working directory)- Externalized Configuration (such as
SPRING_APPLICATION_JSON, system environment variables, and system properties) - External Config Sources introduced via
spring.config.import(including Nacos, Consul, and Vault)
The spring.config.import property allows applications to bind multiple configuration servers simultaneously and supports ${} placeholders to fetch values dynamically from the environment.
Docker and Kubernetes Multi-Environment Strategy
1. Docker Image Practices
- Build Phase: Ensure that no environment-specific variables or Nacos addresses are hardcoded into the
Dockerfile. Retain only placeholders (e.g.,${nacos.namespace}) in configuration files. - Runtime Phase: Inject runtime parameters using container environment variables, such as
-e NACOS_NAMESPACE=xxxx -e SPRING_PROFILES_ACTIVE=dev.
2. Kubernetes ConfigMaps and Secrets
| Resource Type | Purpose | Example Command |
|---|---|---|
| ConfigMap | Stores non-sensitive configurations like bootstrap.yml or logging rules |
kubectl create configmap app-config --from-file=bootstrap.yml |
| Secret | Stores sensitive data such as Nacos credentials or TLS certificates | kubectl create secret generic nacos-cred --from-literal=username=admin --from-literal=password=****** |
These resources can be seamlessly injected into container runtimes using envFrom or explicit env definitions within deployment manifests.
Mapping Nacos to Spring Boot
1. bootstrap.yml Configuration Example
spring:
application:
name: demo-service
cloud:
nacos:
config:
server-addr: ${NACOS_SERVER:127.0.0.1:8848}
username: ${NACOS_USERNAME:nacos}
password: ${NACOS_PASSWORD:nacos}
namespace: ${NACOS_NAMESPACE:public}
file-extension: yaml
shared-configs:
- data-id: common.yaml
refresh: true
- The
NACOS_NAMESPACEis populated dynamically through container environment variables, allowing the same container image to adapt to different isolation boundaries. shared-configslets services pull universal parameters (such as global logging or rate-limiting rules) that remain consistent across all deployment stages.
2. Remote Configuration Management in Nacos
| Namespace | Data ID | Content Example (application-dev.yaml) |
|---|---|---|
| dev | demo-service.yaml |
server.port: 8081datasource.url: jdbc:mysql://dev-db:3306/demo |
| test | demo-service.yaml |
server.port: 8082datasource.url: jdbc:mysql://test-db:3306/demo |
| prod | demo-service.yaml |
server.port: 80datasource.url: jdbc:mysql://prod-db:3306/demo |
During startup, Spring Boot automatically fetches the targeted Data ID from the active Nacos namespace, overriding local default properties where applicable.
Practical Implementation
1. Dockerfile
# Multi-stage build using Eclipse Temurin JDK 17
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN ./mvnw -B package -DskipTests
FROM eclipse-temurin:17-jre-alpine
VOLUME /tmp
ARG JAR_FILE=target/demo-service.jar
COPY --from=builder /app/${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Note: The image remains agnostic of any specific Nacos endpoints or namespace IDs, deferring those values entirely to runtime configuration.
2. Kubernetes Deployment Manifest (demo-deploy.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-service
labels:
app: demo-service
spec:
replicas: 2
selector:
matchLabels:
app: demo-service
template:
metadata:
labels:
app: demo-service
spec:
containers:
- name: demo
image: registry.example.com/demo-service:1.0.0
ports:
- containerPort: 8080
env:
- name: NACOS_SERVER
value: "nacos-server.nacos.svc.cluster.local:8848"
- name: NACOS_USERNAME
valueFrom:
secretKeyRef:
name: nacos-cred
key: username
- name: NACOS_PASSWORD
valueFrom:
secretKeyRef:
name: nacos-cred
key: password
- name: NACOS_NAMESPACE
valueFrom:
configMapKeyRef:
name: env-config
key: nacos.namespace # e.g., dev / test / prod
- name: SPRING_PROFILES_ACTIVE
valueFrom:
configMapKeyRef:
name: env-config
key: spring.profiles.active
envFrom:
- configMapRef:
name: app-config
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
- Values stored in the
env-configConfigMap determine the runtime environment profile. - Modifying the ConfigMap allows operators to reconfigure environment variables without rebuilding or redeploying container images.
3. Verification Workflow
# 1. Deploy Nacos infrastructure
# 2. Apply ConfigMaps and Secrets
kubectl apply -f env-config.yaml
kubectl apply -f app-config.yaml
# 3. Deploy the microservice workload
kubectl apply -f demo-deploy.yaml
# 4. Inspect container logs to verify targeted namespace and Data ID loading
kubectl logs -f deployment/demo-service -c demo
Successful initialization should output log entries resembling:
2026-10-26 10:12:34.567 INFO 12345 --- [ main] o.s.c.nacos.NacosPropertySourceLocator : Loading Nacos config from namespace: dev, dataId: demo-service.yaml
Troubleshooting and Debugging Tips
Incorrect Namespace ID
- Symptom: Startup errors indicating
namespace not found, or accidental fallback to thepublicnamespace. - Solution: Query the Nacos console API (
curl http://nacos:8848/nacos/v1/console/namespaces) to retrieve accurate ID strings and verify environment variables.
- Symptom: Startup errors indicating
Dynamic Refresh Failures
- Symptom: Applications retain cached properties after configuration updates occur in Nacos.
- Solution: Enable
refresh: truewithin configuration blocks and annotate target beans with@RefreshScope.
Multi-Environment Conflicts
- Symptom: Overlapping configurations when multiple stages share identical
Data IDnames. - Solution: Distinguish configurations by suffixing names per environment:
data-id: ${spring.application.name}-${spring.profiles.active}.yaml
- Symptom: Overlapping configurations when multiple stages share identical
ConfigMap Stale State in Kubernetes
- Symptom: Pods continue using legacy namespace definitions after an update.
- Solution: Trigger a rolling restart (
kubectl rollout restart deployment/demo-service) to force pods to pick up updated ConfigMap mounts.
Summary
- Nacos Namespaces provide robust logical isolation for multi-environment deployments. Combined with Spring Boot's native property bootstrapping and placeholders, they enable truly environment-agnostic artifacts.
- Decoupling build-time artifacts from runtime configurations ensures that CI/CD pipelines remain clean, while operational properties are injected via container orchestration tools.
- Managing environment switching through Kubernetes ConfigMaps minimizes operational overhead, allowing engineers to transition workloads across development, staging, and production tiers effortlessly.