Manage environment-specific configurations securely by separating configuration from code, using AWS Secrets Manager or Parameter Store for secret storage, injecting secrets at runtime via IAM roles, and implementing environment-specific configuration files with fallback mechanisms.
Managing environment-specific configurations (development, staging, production) in a Docker/AWS environment requires a fundamental shift from embedding configurations in images to injecting them at runtime. The core principle is separation of concerns: the Docker image should be identical across all environments, with environment-specific values provided when the container runs. This approach ensures consistency, security, and the ability to promote the same image through your deployment pipeline without rebuilding[citation:1][citation:3].
AWS Systems Manager Parameter Store: Store configuration values and secrets as parameters with hierarchical paths like /prod/my-app/DATABASE_URL. Use the SecureString type with KMS encryption for sensitive data[citation:1][citation:7]. Supports versioning and IAM-based access control.
AWS Secrets Manager: Best for secrets requiring automatic rotation, such as database passwords. Provides additional features like cross-account sharing and random secret generation. Recommended for credentials that need regular rotation[citation:8][citation:9].
Encrypted S3 Buckets: For larger configuration files or when you need to store structured config data, use server-side encryption (SSE-KMS) to secure files at rest. Your application must be written to fetch from S3 at startup[citation:8].
In containerized environments, never embed AWS credentials in your Docker image. Instead, use IAM roles attached to the underlying compute resource (EC2, ECS, EKS) to grant permission to access Parameter Store or Secrets Manager[citation:1][citation:8]. The container then uses the instance or task role to fetch configuration at startup.
Separate AWS Accounts for Environments: Use distinct AWS accounts for dev, staging, and production. This creates hard isolation boundaries, limits blast radius, and enables applying consistent guardrails at the organizational unit level[citation:3].
No Hardcoded Secrets: Never store secrets in Docker images, Dockerfiles, or environment variables in source code. Always fetch at runtime[citation:1][citation:7].
Use Parameter Hierarchies: Organize parameters with hierarchical paths like /dev/my-app/database/url and /prod/my-app/database/url. This enables recursive fetching and clear environment separation[citation:1].
Rotate Secrets Regularly: For Secrets Manager, enable automatic rotation. For Parameter Store, implement manual rotation procedures and set expiration alerts[citation:8][citation:10].
Audit Access: Use CloudTrail to log all access to configuration and secret stores. Monitor for unauthorized access attempts[citation:6][citation:10].
For local development, maintain a .env file with development values (never committed to version control) as a fallback. Use tools like dotenv to load these values when running containers locally. The same Docker image that fetches secrets from Parameter Store in production can use local .env files in development, ensuring consistency[citation:1][citation:7].
IAM Least Privilege: Grant the IAM role only permissions to read specific parameter paths (e.g., arn:aws:ssm:region:account:parameter/prod/my-app/*), never wildcards[citation:3][citation:10].
Encryption at Rest: Always use SecureString in Parameter Store, which encrypts values using KMS. For Secrets Manager, encryption is automatic[citation:1][citation:3].
Encryption in Transit: Enforce TLS for all connections to AWS services. The AWS CLI and SDKs use TLS by default[citation:6].
No Privileged Mode: When building images in CI/CD, use AWS CodeBuild's Docker Server capability which eliminates the need for privileged mode, improving security[citation:5].
Image Scanning: Scan images for vulnerabilities before deployment. Amazon Inspector can automate this in CI/CD pipelines[citation:3].