Docker Secrets Management: A Practical Guide

DevOpsDevOps Best PracticesDevOps Tools

YOUR COSMETIC CARE STARTS HERE

Find the Best Cosmetic Hospitals

Trusted • Curated • Easy

Looking for the right place for a cosmetic procedure? Explore top cosmetic hospitals in one place and choose with confidence.

“Small steps lead to big changes — today is a perfect day to begin.”

Explore Cosmetic Hospitals Compare hospitals, services & options quickly.

✓ Shortlist providers • ✓ Review options • ✓ Take the next step with confidence

Sensitive credentials leaking into public repositories or environment variables is one of the most common and costly security mistakes in software development. As the number of services in a typical stack grows, so does the surface area for accidental exposure. Docker Secrets, introduced in Docker 1.13, provides a built-in mechanism for securely distributing sensitive data — such as passwords, API keys, and TLS certificates — to services running in a Docker Swarm.

This guide walks through the core workflow: creating secrets, building an overlay network to exchange them, attaching them to services, and rotating them without touching application code.

Swarm Only: Why Docker Secrets Requires Swarm Mode

Docker Secrets are a Swarm-native feature. The underlying security model — encrypted storage on manager nodes, encrypted in-flight delivery over the Swarm control plane, and in-memory-only exposure inside containers — relies on Swarm infrastructure. Standalone containers created with docker run cannot consume secrets in the same way.

If you need secrets in a single-container workflow, you can still use Swarm mode with a service scaled to one replica (--replicas 1). Docker Desktop (Mac and Windows) supports single-node Swarm mode, which is sufficient for local development and testing. For a multi-node setup on a laptop you can use Docker Machine to provision additional nodes and form a two-node Swarm.

All docker secret commands must be run from a Swarm manager node.

Creating Secrets

Secrets are created from standard input or a file. This makes it straightforward to pipe the output of a password generator directly into Docker. For example, to create a random base64-encoded password for a MariaDB user:

openssl rand -base64 20 | docker secret create mariadb_password -

The command returns the ID of the newly created secret. The secret value is encrypted and stored on the Swarm manager; you cannot retrieve the plaintext value after creation.

Create a second secret for the MariaDB root password:

openssl rand -base64 20 | docker secret create mariadb_root_password -

To list all secrets currently stored in the Swarm:

docker secret ls

The listing shows secret names and IDs but never the secret values themselves.

Creating a Private Overlay Network

Services that need to share secrets should communicate over a dedicated overlay network. This isolates traffic and ensures that secrets are only accessible within the defined network boundary:

docker network create -d overlay mariadb_private

As with secrets, this returns an ID. Use docker network ls to review existing networks.

Attaching Secrets to Services

The following example sets up two services — a MariaDB database and a Python web application — that share secrets over the private overlay network.

MariaDB Service

When a secret is attached to a service, Docker mounts it as a file under /run/secrets/<target> inside the container. Many official images support _FILE environment variable conventions to read credentials from these files instead of from plain environment variables — which would otherwise appear in process listings and docker inspect output.

docker service create \
   --name mariadb \
   --replicas 1 \
   --network mariadb_private \
   --mount type=volume,source=mydata,destination=/var/lib/mariadb \
   --secret source=mariadb_root_password,target=mariadb_root_password \
   --secret source=mariadb_password,target=mariadb_password \
   -e MARIADB_ROOT_PASSWORD_FILE="/run/secrets/mariadb_root_password" \
   -e MARIADB_PASSWORD_FILE="/run/secrets/mariadb_password" \
   -e MARIADB_USER="python" \
   -e MARIADB_DATABASE="python" \
   mariadb:latestCode language: JavaScript (javascript)

Python Application Service

The Python service joins the same private network and receives the secrets mapped to application-specific target names. The mode=0400 flag restricts the secret file to be readable only by the file owner, reducing the risk of accidental exposure inside the container.

docker service create \
   --name cspython \
   --replicas 1 \
   --network mariadb_private \
   --publish 50000:5000 \
   --mount type=volume,source=pydata,destination=/var/www/html \
   --secret source=mariadb_root_password,target=python_root_password,mode=0400 \
   --secret source=mariadb_password,target=python_password,mode=0400 \
   -e PYTHON_DB_USER="python" \
   -e PYTHON_DB_ROOT_PASSWORD_FILE="/run/secrets/python_root_password" \
   -e PYTHON_DB_PASSWORD_FILE="/run/secrets/python_password" \
   -e PYTHON_DB_HOST="mariadb:3306" \
   -e PYTHON_DB_NAME="python" \
   chrischinchilla/cspython:latestCode language: JavaScript (javascript)

Note: In a production setup, the application service should only have access to the least-privileged database user credentials. Root-level credentials should be used only for provisioning and should not be distributed to application containers.

Reading Secrets in Application Code

Inside the container, the application reads the password from the secret file rather than from a plain environment variable. The following Python example illustrates this pattern using the file path stored in an environment variable:

import os
import MySQLdb

# Read the password from the secret file
password_file = os.environ['PYTHON_DB_PASSWORD_FILE']
with open(password_file, 'r') as f:
    password = f.read().strip()

db = MySQLdb.connect(
    host=os.environ['PYTHON_DB_HOST'],
    user=os.environ['PYTHON_DB_USER'],
    passwd=password,
    db=os.environ['PYTHON_DB_NAME']
)

cur = db.cursor()
# ... application logic ...
db.close()Code language: PHP (php)

The key pattern here is: the environment variable holds a file path, and the application reads the actual secret value from that file at runtime. This keeps secrets out of environment variable listings entirely.

Rotating Secrets

Rotating credentials regularly is a security best practice, but it is often skipped because it requires coordinated changes across infrastructure and code. Docker Secrets makes rotation operationally straightforward: you create a new secret, update services to use it, and remove the old one — all without modifying application code.

Step 1: Create the new secret:

openssl rand -base64 20 | docker secret create mariadb_password_v2 -

Step 2: Remove the old secret from the MariaDB service:

docker service update \
     --secret-rm mariadb_password \
     mariadb

Step 3: Add the new secret to the MariaDB service, keeping the same target path so the application does not need to change:

docker service update \
     --secret-add source=mariadb_password_v2,target=mariadb_password \
     mariadb

Step 4: Update the Python service in a single command to swap the secret atomically:

docker service update \
     --secret-rm mariadb_password \
     --secret-add source=mariadb_password_v2,target=python_password,mode=0400 \
     cspython

Step 5: Delete the old secret from the Swarm once all services have been updated:

docker secret rm mariadb_password

Note that a docker service update causes a rolling restart of the service tasks. Plan rotations during a maintenance window or ensure your application handles brief restarts gracefully.

Key Takeaways

  • Never hard-code credentials in images, Dockerfiles, or environment variables passed as plain text. Use Docker Secrets or an equivalent secrets manager.
  • Secrets are mounted as files under /run/secrets/ inside the container and exist only in memory — they are not written to the container’s writable layer.
  • Use _FILE conventions when supported by the image (many official images from Docker Hub support this pattern) to read credentials from secret files automatically.
  • Rotate secrets regularly using docker service update to swap secrets without application code changes.
  • Limit secret scope: only grant each service access to the secrets it actually needs.

Docker Secrets provides a practical, low-overhead secrets management solution for teams already using Docker Swarm. For more advanced requirements — such as dynamic secrets, fine-grained access policies, or multi-platform support — consider pairing it with a dedicated secrets manager such as HashiCorp Vault.

0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x