How do you pass environment variables to a Spring Boot app running in Docker?
Fast recall
Quick revision
Core answer
docker run -e NAME=value, --env-file, Compose environment/env_file, or mounted configuration. Spring Boot maps environment names such as SPRING_DATASOURCE_URL into its Environment using relaxed binding and precedence rules. Do not put long-lived secrets directly in image ENV, source-controlled Compose files, or command history.Interview-ready guide
Interview answer
I provide Spring Boot runtime configuration through the container environment or mounted configuration rather than rebuilding one image per environment. With Docker I can use -e SPRING_DATASOURCE_URL=... or --env-file; Compose offers environment and env_file. Spring Boot's relaxed binding maps the uppercase underscore form to the canonical property name.
For example, SPRING_DATASOURCE_URL can override a default from packaged configuration according to Spring Boot's property-source precedence. For groups of values or sensitive data, a mounted configuration tree or the target platform's config/secret mechanism may be clearer.
Environment values are visible to processes and inspection paths with sufficient access, and command-line values can remain in shell history. I therefore do not bake passwords into Dockerfile ENV or commit them to Compose. I validate required values at startup and consult the full Spring Boot precedence model instead of assuming every external value wins in every situation.
How do you pass environment variables to a Spring Boot app running in Docker
Direct Answer
At runtime, pass configuration with docker run -e NAME=value, --env-file, Compose environment/env_file, or mounted configuration. Spring Boot maps environment names such as SPRING_DATASOURCE_URL into its Environment using relaxed binding and precedence rules. Do not put long-lived secrets directly in image ENV, source-controlled Compose files, or command history.
Code Example
docker run -d \
--name order-service \
-p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://postgres-db:5432/orders \
-e SPRING_DATASOURCE_USERNAME=orderuser \
-e SPRING_DATASOURCE_PASSWORD=secret123 \
-e SERVER_PORT=8080 \
order-service:latest
# In docker-compose.yml:
services:
order-service:
image: order-service:latest
environment:
SPRING_PROFILES_ACTIVE: prod
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres-db:5432/orders
SPRING_DATASOURCE_USERNAME: orderuser
SPRING_DATASOURCE_PASSWORD: secret123
ports:
- "8080:8080"
Common Mistakes & Pitfalls
- Hardcoding production config in application.properties: Freshers put spring.datasource.url=jdbc:postgresql://prod-db:5432/orders directly in the properties file, meaning the same image can't run in dev or test environments without rebuilding. Use environment variables instead and keep only dev defaults in properties files.
- Not using relaxed binding: Freshers manually read environment variables with System.getenv("DB_URL") and set properties programmatically. Spring Boot already does this automatically — just use standard naming like SPRING_DATASOURCE_URL and it maps to spring.datasource.url.
- Passing secrets in Dockerfile with ENV: Writing ENV SPRING_DATASOURCE_PASSWORD=secret123 in the Dockerfile bakes the secret into the image layer permanently, visible to anyone who pulls the image. Pass secrets at runtime with -e or from a secrets manager, never in the Dockerfile.
- Forgetting spring.profiles.active: Freshers pass database config but forget to activate the production profile with -e SPRING_PROFILES_ACTIVE=prod, so Spring Boot still loads dev configuration from application-dev.yml.
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.