Designing Spring Boot Active Profile Switching Between docker-compose and ECS
Introduction
When running a Spring Boot app across multiple environments, it’s crucial to precisely understand which application.yml is being applied.
- Local development:
application-local.yml - Docker Compose:
application-docker.yml - AWS ECS (production):
application-prod.yml
This article documents the profile switching design and how to pass configuration on ECS.
Spring Boot Profile Basics
When you create a file named application-{profile}.yml, it is loaded only when that profile is active.
src/main/resources/
application.yml ← common to all environments
application-local.yml ← for local development
application-docker.yml ← for Docker Compose
application-prod.yml ← for production (ECS)
How to specify a profile:
# Specify at startup
java -jar app.jar --spring.profiles.active=prod
# Specify via environment variable (Docker-friendly)
SPRING_PROFILES_ACTIVE=prod java -jar app.jar
Configuration Files per Environment
application.yml (common to all environments)
spring:
application:
name: dvd-rental-customer-backend
datasource:
driver-class-name: org.postgresql.Driver
jpa:
open-in-view: false
server:
port: 8082
application-local.yml
spring:
datasource:
url: jdbc:postgresql://localhost:15433/dvdrental
username: postgres
password: postgres
thymeleaf:
cache: false
logging:
level:
com.example: DEBUG
application-docker.yml
spring:
datasource:
# Connect to DB using Docker Compose service name
url: jdbc:postgresql://postgres:5432/dvdrental
username: postgres
password: postgres
application-prod.yml
spring:
datasource:
# Production DB URL obtained from environment variables
url: ${DATABASE_URL}
username: ${DATABASE_USERNAME}
password: ${DATABASE_PASSWORD}
logging:
level:
root: WARN
com.example: INFO
Important: Do not hard-code sensitive production information in yaml. Always pass it via environment variables.
Specifying Profile in Docker Compose
# compose.yml
services:
app:
image: dvd-rental-customer-backend:latest
environment:
SPRING_PROFILES_ACTIVE: docker # ← specify here
TZ: Asia/Tokyo
ports:
- "8082:8082"
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16
environment:
POSTGRES_DB: dvdrental
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
Specifying Profile on ECS (AWS Fargate)
Set container environment variables in the ECS task definition.
CDK Configuration Example
// cdk/lib/app-stack.ts
const taskDefinition = new ecs.FargateTaskDefinition(this, 'AppTask', {
memoryLimitMiB: 512,
cpu: 256,
});
const container = taskDefinition.addContainer('AppContainer', {
image: ecs.ContainerImage.fromEcrRepository(ecrRepo, 'latest'),
environment: {
// Environment variables (plain text)
SPRING_PROFILES_ACTIVE: 'prod',
TZ: 'Asia/Tokyo',
},
secrets: {
// Sensitive info obtained from SSM Parameter Store
DATABASE_URL: ecs.Secret.fromSsmParameter(
ssm.StringParameter.fromStringParameterName(this, 'DbUrl', '/dvd-rental/db-url')
),
DATABASE_USERNAME: ecs.Secret.fromSsmParameter(
ssm.StringParameter.fromStringParameterName(this, 'DbUser', '/dvd-rental/db-username')
),
DATABASE_PASSWORD: ecs.Secret.fromSsmParameter(
ssm.StringParameter.fromStringParameterName(this, 'DbPassword', '/dvd-rental/db-password')
),
},
logging: ecs.LogDrivers.awsLogs({
streamPrefix: 'dvd-rental',
logGroup: logGroup,
}),
});
How to Verify Profile on ECS
After deployment, verify the correct profile is applied via CloudWatch Logs.
Spring Boot outputs the active profile to logs at startup:
INFO o.s.b.SpringApplication - The following 1 profile is active: "prod"
INFO o.s.b.w.embedded.tomcat.TomcatWebServer - Tomcat initialized with port 8082 (http)
Confirm it shows "prod" before considering the deployment complete.
# Verify profile in CloudWatch Logs
aws logs filter-log-events \
--log-group-name /dvd-rental/app \
--filter-pattern "profiles is active" \
--region ap-northeast-1
Common Mistakes
① Forgetting to specify a profile in Docker Compose
Without specifying a profile, the default profile is used.
Even if application-docker.yml exists, it won’t be read.
# NG (no profile specified)
services:
app:
environment:
TZ: Asia/Tokyo
# OK
services:
app:
environment:
SPRING_PROFILES_ACTIVE: docker # ← required
TZ: Asia/Tokyo
② Including local application-local.yml in the Docker image
If the production image contains local connection info like localhost:15433, it may be referenced unintentionally.
# Exclude in .dockerignore
src/main/resources/application-local.yml
③ Getting uppercase/lowercase wrong for environment variables
Spring Boot accepts both SPRING_PROFILES_ACTIVE (all caps, underscore-separated) and spring.profiles.active (dot-separated).
For Docker environment variables, use the all-caps underscore format.
Summary
| Environment | Profile | How to Set |
|---|---|---|
| Local development | local | IDE Run config or JVM args |
| Docker Compose | docker | environment: SPRING_PROFILES_ACTIVE: docker |
| ECS (production) | prod | Task definition environment |
- Do not hard-code sensitive info in
application-prod.yml; pass it via environment variables or SSM - After deployment, always verify “active profile” in CloudWatch Logs
- Keep profile names simple — around three types: local, Docker, and production — rather than creating one per environment
Article Map for This Series
→ Building a DVD Rental App for End Users — Overall Vue 3 + Spring Boot Structure with Admin App and Article Map
→ Building a DVD Rental Admin App with Spring Boot + Thymeleaf Based on the dvdrental Sample DB