civil-and-structural-engineering
How to Use Docker Secrets for Managing Sensitive Configuration Data
Table of Contents
Understanding Docker Secrets and Their Purpose
In modern containerized deployments, safeguarding sensitive configuration data such as database passwords, API tokens, TLS certificates, and encryption keys is non-negotiable. Exposing these values—whether through hard‑coded environment variables, unencrypted configuration files, or plaintext in Docker images—creates serious security vulnerabilities. Docker Secrets, a feature integrated into Docker Swarm mode, provides a formal, encrypted mechanism for managing and delivering such sensitive data to containers at runtime.
Unlike environment variables, which remain visible in container inspect output and process lists, Docker Secrets are never exposed outside the container’s runtime environment. Secrets are encrypted during transit and at rest, stored in the Swarm’s internal distributed store, and mounted as temporary files inside the container’s /run/secrets/ directory. This design ensures that secrets are only available to containers that explicitly require them and are not leaked into logs, image layers, or external tooling.
Prerequisites for Using Docker Secrets
Before diving into implementation, confirm that your environment meets the following requirements:
- Docker Engine 1.13 or later – Docker Secrets is not available in older versions.
- Docker Swarm mode activated – Secrets are a Swarm feature, so you must initialize or join a Swarm cluster, even on a single node.
- Appropriate permissions – To create and manage secrets, you need Swarm manager privileges. Workers can only consume secrets assigned to services.
- Network connectivity – In multi‑node clusters, all nodes must be able to communicate with the Swarm manager for secret distribution.
If you are not yet using Swarm, you may need to evaluate alternative secret management approaches for standalone containers. Docker Compose v3.1 and later support secrets for local deployments, but production environments strongly benefit from the full Swarm lifecycle.
Setting Up Docker Swarm (if not already done)
Docker Secrets depend on Swarm’s control plane. To initialize a Swarm on your active node, run:
docker swarm init
If you are running a single‑node cluster for testing, this command is sufficient. The output will display a manager token that you can use to join additional manager or worker nodes. For a production setup, consider using multiple managers for high availability. The Swarm mode also enables features like service discovery, rolling updates, and encrypted overlay networks, which complement secret management.
To verify that Swarm is active, use:
docker info | grep Swarm
Expect the response: Swarm: active.
Creating Docker Secrets – Two Methods
Secrets can be created from files or directly from standard input. Both methods ensure that the secret data never appears in your shell history or command logs if used carefully.
Creating a Secret from a File
This approach is ideal when you already have a file containing the secret value, such as a TLS certificate or a password file. Use the docker secret create command with a name and the file path:
docker secret create db_password ./my_db_password.txt
The file content is read and encrypted before storage. The original file can be removed after creation; it is no longer needed by Docker.
Creating a Secret from Standard Input
For inline secret values (e.g., generated passwords), pipe the value directly to docker secret create using the hyphen (-) to denote stdin:
echo "my_secure_password" | docker secret create db_password -
Be cautious: echoing a plaintext secret into a command can reveal it in shell history. In automated scripts, consider using input redirection or external tools to avoid echo. Alternatively, use cat with a secure temporary file.
You can also read secrets from a file using input redirection:
docker secret create db_password < ./my_db_password.txt
This method avoids the echo command and is safer in scripted environments.
Using Docker Secrets in Services
Once a secret exists in the Swarm, you must explicitly attach it to a service. The secret is then mounted as a file inside the container, available to the application at runtime.
Injecting a Secret into a Service
When creating a new service, use the --secret flag:
docker service create \
--name my_app \
--secret db_password \
--publish 80:80 \
my_image:latest
For existing services, update them to add or remove secrets:
docker service update \
--secret-add api_key \
--secret-rm old_api_key \
my_app
Multiple secrets can be attached by repeating the --secret flag. Secrets are assigned to the service at creation or update; they are immutable in content—to change a secret value, you must create a new secret, update the service, and remove the old one.
How Secrets Are Mounted Inside Containers
Inside the container, each secret appears as a regular file under /run/secrets/. The filename matches the secret name (e.g., /run/secrets/db_password). The file is a mount of an encrypted tmpfs, meaning it never touches persistent storage on the host. To read the secret from within an application:
- Bash:
cat /run/secrets/db_password - Python:
with open('/run/secrets/db_password') as f: password = f.read().strip() - Node.js:
const password = fs.readFileSync('/run/secrets/db_password', 'utf8').trim();
Applications should treat these files as any other sensitive input: read them at startup, store them in memory, and avoid logging or printing the values.
By default, the secret file is owned by root with permissions 0400. If your container runs as a non‑root user, you may need to adjust permissions using the --secret options, such as:
docker service create \
--name my_app \
--secret source=db_password,uid=1000,gid=1000,mode=0440 \
my_image
Managing Secrets – Listing, Updating, Removing
To view all secrets in the Swarm:
docker secret ls
To inspect details of a specific secret (note: the actual data is never displayed):
docker secret inspect db_password
To remove a secret that is no longer in use:
docker secret rm db_password
Removing a secret that is currently attached to a running service will fail. You must first remove it from all services using docker service update --secret-rm.
Since secrets are immutable, updating a value requires a naming convention (e.g., db_password_v2) or a workflow that creates a new secret, updates the service, then removes the old one. This pattern naturally supports rotation with zero downtime.
Best Practices for Docker Secrets Management
Applying these practices will help you build a secure, maintainable secret management strategy.
Principle of Least Privilege
Only attach secrets to services that genuinely need them. For example, a web front‑end that never connects to the database should not have the db_password secret. Restricting secret access reduces the blast radius of a potential container compromise. Use separate secrets for different environments (e.g., prod_db_password vs. staging_db_password) and avoid reusing credentials.
Avoid Storing Secrets in Images or Environment Variables
Never bake secrets into Docker images—doing so embeds them in image layers, making them accessible to anyone who can pull the image or inspect its history. Similarly, environment variables remain visible in docker inspect, container logs, and runtime process listings. Docker Secrets bypass these exposure points, making them the recommended approach for Swarm deployments.
For more details, refer to the official Docker Secrets documentation.
Regular Rotation of Secrets
Rotate secrets on a scheduled basis (e.g., every 30 to 90 days) or immediately after a security incident. Leverage the immutable nature of secrets by creating new versions and updating services. Automate rotation using CI/CD pipelines or configuration management tools. Ensure your application can reload secrets without a full container restart if possible—for example, by watching the /run/secrets/ directory for changes or by using a signal handler.
Read Docker’s blog on secret management best practices for further insight.
Use of Access Control and Auditing
In multi‑team environments, restrict who can create, read, and delete secrets using Swarm’s role‑based access control (RBAC) or external signing. Audit logs can be obtained via Docker’s event stream or by integrating with logging systems. Track secret creation and service updates to detect unauthorized changes.
Consider Alternatives for Non‑Swarm Environments
If you are running standalone containers or using orchestration tools other than Swarm, Docker Secrets are not available. In those cases, consider:
- Hashicorp Vault – A dedicated secrets management tool that can inject secrets into containers via sidecar proxies or environment variables. Integration with Docker is well documented.
- Kubernetes Secrets – If migrating to Kubernetes, its built‑in Secrets provide similar functionality with more granular access policies.
- Docker Compose secrets – For local development, Compose v3.1+ supports a simplified secret mechanism (though not encrypted at rest like Swarm).
Limitations and Considerations
While Docker Secrets improve security, they have important limitations:
- Swarm requirement – Secrets do not work outside Swarm mode. Standalone Docker containers cannot use them natively.
- Immutability – Secrets cannot be updated in place. You must create a new secret and update the service, which may complicate rapid rotation without careful orchestration.
- Size limit – Each secret is limited to 500 KiB. For larger files, break them into chunks or use alternative solutions.
- No encryption at rest on some filesystems – The Swarm store encrypts secrets, but the underlying Docker data directory (usually
/var/lib/docker) should itself be encrypted, especially on hosts with direct disk access. - Application awareness – Your application must be designed to read secrets from
/run/secrets/rather than from environment variables or config files. This may require code changes.
Understanding these constraints helps you decide whether Docker Secrets are appropriate for your use case or if you should layer additional tooling on top.
Conclusion
Docker Secrets provide a straightforward, built‑in solution for managing sensitive data in Swarm‑based container deployments. By encrypting secrets at rest and in transit, mounting them as ephemeral files, and restricting access to only the services that need them, you can significantly reduce the attack surface of your containerized applications. The process of creating, attaching, and rotating secrets is simple once Swarm is initialized, making it an excellent starting point for secure configuration management.
However, secrets alone are not a complete security strategy. Combine them with network policies, read‑only root filesystems, secure base images, and regular vulnerability scanning to build defense in depth. For organizations scaling beyond a single Swarm cluster or requiring more advanced secret lifecycle management, evaluating dedicated tools like Vault or a transition to Kubernetes may be warranted. Regardless of the approach, moving secrets out of images and environment variables is a critical step toward production‑grade container security.