Docker + Azure Key Vault + Managed Identity
This document describes a correct and practical way to use Azure Key Vault secrets in an application running in a Docker container.
Goal: do not keep secrets in .env files or in the repository. Fetch them through managed identity instead.
Key Clarification
The previous version of this document suggested installing the Azure Arc Connected Machine Agent inside the application container. This approach is not recommended for a typical ephemeral Docker container.
Why:
- the Arc agent is intended for the host (machine/VM), not for a standard application container,
- it requires elevated privileges and complicates security,
- it makes maintenance and scaling harder,
- it is not the simplest way to make DefaultAzureCredential work.
Conclusion: identity and Azure integration should be provided at the platform or host layer, while the application container should stay as simple as possible.
Recommended Architecture
Choose one of these two options.
Option A (preferred): Platform with native Managed Identity
Examples:
- Azure Container Apps,
- Azure App Service (Web App for Containers),
- AKS with Workload Identity.
How it works:
- the platform provides managed identity,
- the app uses Azure SDK and DefaultAzureCredential,
- secrets are fetched from Key Vault at runtime.
Benefits:
- the fewest custom moving parts to maintain,
- good alignment with cloud-native patterns,
- no need to run the Arc agent inside the container.
Option B: VM + Docker / docker-compose
If you run on your own machine (for example an Ubuntu VM) with Docker:
- configure identity on the host, not in the container,
- the containerized app can fetch secrets through SDK only if the host provides a valid identity mechanism and access,
- alternatively, the host can fetch secrets at startup and pass them to the app process as environment variables (a compromise).
Notes:
- still avoid storing secrets in the repository,
- limit secret lifetime and exposure,
- follow least-privilege access.
Application Implementation (Python / Django)
1. Dependencies
Add these libraries:
- azure-identity
- azure-keyvault-secrets
Installation example:
pip install azure-identity azure-keyvault-secrets
2. Secret Retrieval Code
Helper module example:
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
def get_secret(vault_name: str, secret_name: str) -> str:
vault_url = f"https://{vault_name}.vault.azure.net"
credential = DefaultAzureCredential()
client = SecretClient(vault_url=vault_url, credential=credential)
secret = client.get_secret(secret_name)
return secret.value
In Django settings, you can load these values during application startup.
3. Environment Configuration
Required minimum:
- Key Vault name (for example KEYVAULT_NAME),
- secret names or a mapping to configuration keys.
Example:
- KEYVAULT_NAME=my-app-kv
- DB_PASSWORD_SECRET_NAME=database-password
Azure Configuration (RBAC)
1. Create a Key Vault with RBAC
az keyvault create \
--name my-app-keyvault \
--resource-group my-app-rg \
--location westeurope \
--enable-rbac-authorization true
2. Enable Managed Identity for the runtime resource
This depends on the platform (Container Apps, App Service, AKS, VM/Arc).
3. Grant Permissions to Key Vault
For read-only secret access, the Key Vault Secrets User role is usually enough.
az role assignment create \
--assignee <identity-principal-id> \
--role "Key Vault Secrets User" \
--scope <key-vault-resource-id>
4. Verify Access
- wait a few minutes for permission propagation,
- test reading a single secret from the application.
What Not to Do
- do not put passwords or API keys in a
.envfile committed to the repository, - do not pass static Service Principal secrets to the container if your goal is to move to Managed Identity,
- do not run the application container with excessive privileges just to run the Arc agent.
Migration from .env to Key Vault
- Identify all secrets currently in
.env. - Add them to Key Vault.
- Replace
.envsecret reads with Key Vault reads (SDK) or with a secure host-side bootstrap. - Keep only non-secret values in
.env(for example feature flags, hostnames). - Deploy and verify startup logs plus critical application paths.
Troubleshooting
Issue: DefaultAzureCredential cannot find an identity
- check whether the runtime environment actually exposes Managed Identity,
- verify the Azure resource configuration,
- verify that the app runs in the same identity context.
Issue: 403 from Key Vault
- check RBAC roles at the correct scope,
- verify that Key Vault has RBAC authorization enabled,
- wait for permission propagation.
Issue: works locally but fails on server
- locally, DefaultAzureCredential may use a different identity source (for example Azure CLI),
- on the server, make sure managed identity is enabled and assigned.
References
- Azure Identity client library for Python
- DefaultAzureCredential overview
- Azure Key Vault secrets client library for Python
- Key Vault RBAC guide
- Managed identities for Azure resources
- Azure Container Apps managed identity
- Azure App Service managed identity
- AKS Workload Identity
- Azure Arc-enabled servers overview
- Azure Arc agent overview