Concepts & Architecture
Docker Secret Operator (DSO) relies on three core concepts: secret URI protocols, dual-mode execution, and the secret lifecycle.
1. Dual-Mode Execution
DSO operates in two distinct modes. The correct mode is auto-detected at runtime.
Local Mode
- Secrets stored in
~/.dso/vault.enc(AES-256-GCM encrypted) - No systemd. No root. No cloud account required.
- The CLI resolves all
dso://anddsofile://URIs in-process at deploy time. - Activated by: running
docker dso initwhich creates the vault file.
Cloud Mode
- Secrets fetched from external providers (HashiCorp Vault, AWS, Azure, Huawei) via plugin binaries.
- A persistent
dso-agentdaemon runs as a systemd service. - Activated by: the presence of
/etc/dso/dso.yamlor./dso.yaml. - Requires setup via
sudo docker dso system setup.
Mode priority order:
--mode=<cloud|local>flagDSO_MODEorDSO_FORCE_MODEenv var/etc/dso/dso.yamlpresent → Cloud./dso.yamlpresent → Cloud~/.dso/vault.encpresent → Local- Neither → guided error with setup instructions
If both a vault and cloud config exist, Cloud Mode wins and a conflict warning is printed.
2. Secret Protocols (dso:// vs dsofile://)
DSO introduces two URI protocols that you embed directly in your docker-compose.yaml:
dsofile:// (Recommended)
Behavior: Injects the secret as a file inside a tmpfs RAM disk (/run/secrets/dso/) inside the container.
Why use it: This is the most secure method. The secret never touches disk. It is completely invisible to docker inspect. Applications designed for production often read secrets from file paths (e.g., POSTGRES_PASSWORD_FILE).
⚠️
dsofile://is only supported in Local Mode. Cloud Mode uses native provider injection directly.
environment:
POSTGRES_PASSWORD_FILE: dsofile://myapp/db_password
dso:// (Environment Variable Injection)
Behavior: Injects the secret value directly as an environment variable.
Why use it: Use this only if the application cannot read from a file path.
Warning: Secrets injected via dso:// are visible via docker inspect <container>.
environment:
STRIPE_KEY: dso://myapp/stripe_key
3. The Agent Runtime
Local Mode Agent
In Local Mode, the agent runs inline — inside the same docker dso up process. It does not persist after the stack is launched (the process exits when docker compose up returns). The lifecycle is:
- CLI reads
~/.dso/vault.encand parses the compose file AST. - It resolves all
dso://anddsofile://URIs in memory. - A temporary in-process agent seeds the secret cache.
- The mutated compose AST is written to a
tmpfs-backed temp file. - Docker Compose receives the sanitized file — secrets are never in the working directory.
Cloud Mode Agent (dso-agent)
In Cloud Mode, a persistent dso-agent systemd service runs on the host. The CLI connects to it via Unix socket (/var/run/dso.sock):
docker dso updetects Cloud Mode from/etc/dso/dso.yaml.- It connects to the running
dso-agentdaemon via socket. - The daemon fetches secrets from the configured provider plugin (e.g.,
dso-provider-vault). - Secrets are returned in-memory to the CLI for compose AST resolution.
- No secrets are written to disk at any stage.
4. Secret Lifecycle
| Stage | Local Mode | Cloud Mode |
|---|---|---|
| Storage | ~/.dso/vault.enc (AES-256-GCM) |
External provider (Vault, AWS, etc.) |
| At deploy | Decrypted in RAM only | Fetched via plugin over IPC |
| In container | tmpfs RAM disk (dsofile://) or env var |
Env var (native provider injection) |
| After container stops | tmpfs wiped automatically |
Nothing persisted locally |
| On container restart | Agent re-injects from RAM cache | Agent re-fetches from provider |
5. Provider Plugins (Cloud Mode Only)
Cloud Mode uses binary plugins to fetch secrets from external backends. Plugins are installed by sudo docker dso system setup and live in /usr/local/lib/dso/plugins/.
| Plugin | Backend | Status |
|---|---|---|
dso-provider-vault |
HashiCorp Vault (KV v2) | ✅ Fully implemented |
dso-provider-aws |
AWS Secrets Manager | ✅ Fully implemented |
dso-provider-azure |
Azure Key Vault | ✅ Fully implemented |
dso-provider-huawei |
Huawei Cloud CSMS | ✅ Fully implemented |
The plugin binary path is logged at runtime: [DSO] Using VAULT provider plugin: /usr/local/lib/dso/plugins/dso-provider-vault.