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 public namespace 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):

  1. Command Line Arguments (e.g., --spring.config.import=nacos:...)
  2. application.yml / application.properties (located in classpath:/, classpath:/config/, or the working directory)
  3. Externalized Configuration (such as SPRING_APPLICATION_JSON, system environment variables, and system properties)
  4. 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_NAMESPACE is populated dynamically through container environment variables, allowing the same container image to adapt to different isolation boundaries.
  • shared-configs lets 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: 8081
datasource.url: jdbc:mysql://dev-db:3306/demo
test demo-service.yaml server.port: 8082
datasource.url: jdbc:mysql://test-db:3306/demo
prod demo-service.yaml server.port: 80
datasource.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-config ConfigMap 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 the public namespace.
    • Solution: Query the Nacos console API (curl http://nacos:8848/nacos/v1/console/namespaces) to retrieve accurate ID strings and verify environment variables.
  • Dynamic Refresh Failures

    • Symptom: Applications retain cached properties after configuration updates occur in Nacos.
    • Solution: Enable refresh: true within configuration blocks and annotate target beans with @RefreshScope.
  • Multi-Environment Conflicts

    • Symptom: Overlapping configurations when multiple stages share identical Data ID names.
    • Solution: Distinguish configurations by suffixing names per environment:
      data-id: ${spring.application.name}-${spring.profiles.active}.yaml
      
  • 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.