How Spring Config Server and .env Collaborate in Multi-Env Microservices

In the AdventureTube backend microservices architecture, configuration management is handled through a collaboration between Spring Cloud Config Server and environment (.env) files. This setup ensures consistency, flexibility, and secure handling of configuration data across different stages of deployment.


🧩 Background of env.XXX File Design

The original idea behind creating env.XXX files was for Docker-based environments, because Docker Compose provides the --env-file option, which:

  • Loads environment variables before any container starts

  • Makes those variables available to Spring Boot during early startup

  • Ensures full compatibility with spring.config.import, Maven build steps, and Config Server resolution

However, when running services outside Docker β€” such as during local development or Maven test execution β€” there is no native mechanism for loading .env files unless manually handled. This is where the custom DotenvEnvironmentPostProcessor comes in:

  • It uses the dotenv package to load .env files manually

  • It applies these values to the Spring Environment during application startup

  • But it runs too late to influence application.yml values such as ${CONFIG_SERVER_URL} in spring.config.import

As a result, for non-Docker scenarios, the only reliable ways to make CONFIG_SERVER_URL work early are:

  • Manually setting environment variables in IntelliJ Run Configurations

  • Defining them in the parent pom.xml using the maven-surefire-plugin, like the following example:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>3.1.2</version>
  <configuration>
    <environmentVariables>
      <SPRING_PROFILES_ACTIVE>mac</SPRING_PROFILES_ACTIVE>
      <CONFIG_SERVER_URL>http://192.168.1.105:9297</CONFIG_SERVER_URL>
    </environmentVariables>
  </configuration>
</plugin>

πŸ”§ Role of .env Files

.env files are used only during the bootstrap phase of each service, mainly in development or local setups. Their purpose is to define variables such as:

SPRING_PROFILES_ACTIVE=dev
CONFIG_SERVER_URI=http://localhost:8888

These values help Spring Boot determine:

  • Which profile to activate

  • Where to locate the Config Server

.env files should never be committed to Git, especially if they contain secrets.


☁️ Role of Spring Cloud Config Server

The Config Server serves as the central source of configuration for all microservices. It pulls configuration files from a Git repository and distributes them based on:

  • Application name (e.g. auth-service, member-service)

  • Active profile (e.g. dev, qa, prod)

πŸ—‚ Example Config Repo Structure:

config-repo/
β”œβ”€β”€ auth-service-dev.yml
β”œβ”€β”€ auth-service-qa.yml
β”œβ”€β”€ member-service-dev.yml
β”œβ”€β”€ application.yml

Sample auth-service-dev.yml:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/authdb
    username: dev_user
    password: ${DB_PASSWORD}

Secrets like DB_PASSWORD are injected via environment variables or a Vault service β€” not stored in Git.


πŸ”„ Collaboration Flow

  1. Developer loads a .env file to export SPRING_PROFILES_ACTIVE and CONFIG_SERVER_URI

  2. Spring Boot reads bootstrap.yml and connects to the Config Server

  3. The service requests its config from config-server/{app-name}-{profile}.yml

  4. The Config Server delivers environment-specific configurations

  5. Secrets are injected dynamically, not stored statically


πŸ§ͺ Current Environment Setup

EnvironmentDescriptionProfile
πŸ§‘β€πŸ’» DeveloperLocal Mac with .env filedev
πŸ“ QA ServerRaspberry Pi (via NGINX Proxy Manager)qa
☁️ ProductionAWS (to be implemented)prod

πŸš€ Service Initiation Paths

The AdventureTube backend supports three distinct initiation processes, each utilizing the combination of .env files and the Config Server:

1. πŸ§ͺ Maven Build/Test Process

  • Used when compiling or packaging the application via Maven.

  • Runs tests by default unless explicitly skipped (-DskipTests).

  • Test phase can pick up environment variables if set in the terminal or CI.

  • If CONFIG_SERVER_URL is needed, it must be injected via Maven profile or system properties β€” .env post-processing won’t apply early enough.

2. πŸ’» IntelliJ Runtime Process

  • Used when running individual services via IntelliJ Run Configurations.

  • Environment variables (SPRING_PROFILES_ACTIVE, CONFIG_SERVER_URL) are set through the Run Config’s Environment Variables section.

  • This process allows live dev/testing with a fully wired Config Server setup.

3. 🐳 Docker Compose Process

  • Initiated via docker-compose up.

  • Uses the --env-file option or env_file: directive in docker-compose.yml to inject variables.

  • These variables are set as real OS-level environment variables, and are available immediately during the Spring Boot config bootstrap phase.


⚠️ Subtle but Critical Distinction: .env via Docker vs. PostProcessor

SourceWhen Available to Spring BootCan Influence spring.config.import?
.env via --env-file in Dockerβœ… Before Spring Boot startsβœ… Yes
.env via DotenvEnvironmentPostProcessor❌ After initial config loading starts❌ No

βœ… Why Docker’s .env Works

  • Docker injects variables before the Spring application launches

  • These are true environment variables, so Spring can resolve them in early YAML parsing (e.g., ${CONFIG_SERVER_URL} in spring.config.import)

❌ Why DotenvEnvironmentPostProcessor Is Too Late

  • PostProcessors run after Spring has already loaded application.yml

  • Any placeholder like ${CONFIG_SERVER_URL} in spring.config.import will fail to resolve if it’s only set in .env via this PostProcessor


βœ… Best Practices Summary

  • πŸ”’ Do not commit secrets to Git β€” use Vault or env vars

  • πŸ”„ Use .env for local-only bootstrap needs

  • πŸ“ Use Spring Config Server for centralized, versioned config

  • 🐳 For Docker, use --env-file or env_file: to inject values early

  • πŸ›  Avoid relying on .env files for early YAML resolution β€” use OS env vars or system properties

This structure provides a scalable, secure, and environment-agnostic way to manage configuration in Spring Boot microservices.

Leave a Comment

Your email address will not be published. Required fields are marked *