Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Use Docker Secrets

Use Docker secrets for sensitive data — Docker.

Focus: use docker secrets for sensitive data

Sponsored

Hardcoding database passwords, API tokens, or SSH keys into your Docker images feels convenient — until one leaked file exposes your entire infrastructure. That lingering .env file in the build context or a hard-coded secret in a Dockerfile is a ticking time bomb in production. This lesson teaches you how to use Docker secrets for sensitive data — a secure, built-in mechanism that keeps credentials out of images, environment variables, and container layers — so you can deploy with confidence.

The problem this lesson solves

Containers need secrets: database passwords, API tokens, TLS certificates, or private keys. The naive approach — putting secrets in environment variables, copying them into images with COPY, or baking them into config files — introduces two fatal flaws:

  • Secrets leak into image layers. Any docker history or image pull exposes the secret forever.
  • Secrets spread across environments. A hard-coded secret in a development image might end up cloned into production.

Even using .env files is risky: if the file is accidentally committed, copied into a volume, or logged during debugging, the secret is compromised. Docker secrets solve this by injecting sensitive data only into the container at runtime — never into the image or the build cache.

Core concept / mental model

Think of Docker secrets as a secure courier service between the Swarm manager and your container. You declare a secret by name, and the manager delivers the actual value (e.g., a password) to only the containers that need it — encrypted in transit and at rest on the manager. The secret is written to a temporary in-memory filesystem (/run/secrets/) inside the container and removed when the container stops.

Key definitions

  • Secret: a blob of data — a password, API key, or certificate — referenced by name.
  • Docker Swarm: the orchestrator that manages secret distribution. Secrets are a Swarm feature, not available for standalone containers.
  • docker secret create: registers a secret with the Swarm manager.
  • /run/secrets/<secret_name>: the default mount point inside the container where the secret contents appear as a plain text file.

This is not about encrypting data at rest in your database — it’s about securing the transmission and storage of secrets between the orchestration layer and the container runtime.

Why not environment variables?

Environment variables are inspectable via docker inspect, docker exec env, or even inside a compromised container. Docker secrets are ephemeral and scope-limited: they exist only as files in the memory of the specific task (container) that needs them.

How it works step by step

1. Initialize your Swarm (one-time)

Secrets require Swarm mode, even on a single-node setup.

docker swarm init

2. Create the secret

Use docker secret create with a file or standard input.

echo "my-super-secret-password" | docker secret create db_password -

The trailing - means read from stdin. Alternatively, use docker secret create db_password ./password.txt.

3. Grant access to a service

When deploying a service with docker service create, attach the secret using the --secret flag.

docker service create \
  --name my_app \
  --secret db_password \
  --publish 3000:3000 \
  my_image:latest

4. Read the secret inside the container

Inside the container, the secret is available as a file at /run/secrets/db_password.

# Python example: read a Docker secret
import os

def read_secret(secret_name):
    secret_path = f"/run/secrets/{secret_name}"
    try:
        with open(secret_path, "r") as f:
            return f.read().strip()
    except FileNotFoundError:
        return os.environ.get(secret_name, "default_fallback")

db_pass = read_secret("db_password")
print(f"DB password length: {len(db_pass)}")

Expected output:

DB password length: 24

5. Clean up

When you remove the service, the secret file is automatically destroyed.

docker service rm my_app
docker secret rm db_password

Hands-on walkthrough

Let’s build a complete end-to-end example with a PostgreSQL service that uses a secret for the password.

Step 1: Create the secret

docker swarm init
echo "s3cureP@ssw0rd!" | docker secret create postgres_password -

Step 2: Deploy PostgreSQL with the secret

docker service create \
  --name postgres \
  --secret postgres_password \
  -e POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydb \
  --publish 5432:5432 \
  postgres:15

Notice we use POSTGRES_PASSWORD_FILE — many Docker images support this pattern instead of POSTGRES_PASSWORD to avoid passing secrets as env vars.

Step 3: Verify the secret inside the container

# Find the container ID
docker ps --filter "name=postgres"

# Confirm the file exists
docker exec <container-id> cat /run/secrets/postgres_password

Expected output:

s3cureP@ssw0rd!

Step 4: Use the secret in a Python application

Let’s write a minimal Python client that connects to PostgreSQL using the secret.

# app.py
import psycopg2
import os

def get_secret(secret_name):
    with open(f"/run/secrets/{secret_name}") as f:
        return f.read().strip()

conn = psycopg2.connect(
    host="postgres",
    user="myuser",
    password=get_secret("postgres_password"),
    dbname="mydb"
)
print("Connected successfully")
conn.close()

Compare options / when to choose what

Method Security Persistence Secret rotation Recommended for
Docker Secrets High (in-memory, encrypted) Ephemeral per container Manual or via service update Production Swarm services
Environment variables Medium (leaked via inspect) Persistent in image if baked Rebuild image Development / quick tests
.env file Low (committed easily) Filesystem Manual Local dev only
Vault/External secret store Very high N/A Automated Large-scale multi-service

Choose Docker secrets when you need a simple, built-in mechanism for Swarm services with zero external dependencies. For more complex rotation or cross-cluster secrets, consider HashiCorp Vault or cloud-native secret managers (AWS Secrets Manager, GCP Secret Manager).

Troubleshooting & edge cases

Secret not appearing in /run/secrets/

  • Ensure the service is running in Swarm mode. Run docker info | grep Swarm — it should say active.
  • Verify the secret exists: docker secret ls.
  • The container must be part of one or more services that have the secret attached.

Permission denied when reading the secret

The secret file is created with root ownership. If your application runs as a non-root user (best practice), adjust the service to mount the secret with the correct UID/GID:

docker service create \
  --name my_app \
  --secret source=db_password,target=db_password \
  --user 1000:1000 \
  my_image

Secret too large

Docker secrets are designed for small blobs (recommended <500 KB). For larger files, consider mounting a volume with proper encryption or using a dedicated secret store.

Updating a secret without restarting the service

Docker does not automatically update secrets inside running containers. To rotate a secret: 1. Create a new secret with a new name (db_password_v2). 2. Update the service to add the new secret and remove the old one. 3. Rebuild your application to read the new file path, or use a symlink approach.

docker service update \
  --secret-rm db_password \
  --secret-add db_password_v2 \
  my_app

Secrets in Docker Compose (Swarm mode)

Docker Compose files can declare secrets only when deployed to a Swarm (using docker stack deploy). Example docker-compose.yml:

version: "3.8"
services:
  app:
    image: my_app
    secrets:
      - db_password
secrets:
  db_password:
    external: true   # created via `docker secret create`

Deploy with:

docker stack deploy -c docker-compose.yml my_stack

What you learned & what's next

You now know how to use Docker secrets for sensitive data — from creating and attaching secrets to reading them inside containers. You understand why secrets are safer than environment variables or image layers, and you’ve seen how to handle common pitfalls like permissions and rotation.

In the next lesson, you’ll explore Docker configs — a similar mechanism for non-sensitive configuration files (like .env templates or JSON configs) that also lives outside the image. You’ll apply both secrets and configs to build a production-ready multi-service stack.

Practice recap

Mini exercise: Deploy a simple Redis service that reads a password from a Docker secret. Create a secret redis_pass with value s3cret, then run docker run -d --name redis-secure --secret redis_pass redis:7-alpine -requirepass $(cat /run/secrets/redis_pass). Verify you can connect using redis-cli -a s3cret.

Common mistakes

  • Trying to use docker secret create without initializing a Swarm — the command fails with a Swarm-related error.
  • Hard-coding the secret value in a Dockerfile COPY instruction, which embeds it into the image layer forever.
  • Forgetting to update the service when rotating a secret — the container holds the old value until recreated.
  • Assuming secrets are automatically updated inside running containers — they are not; you must explicitly restart the service.

Variations

  1. Use docker secret create my_secret - with stdin for piping output from password generators.
  2. Specify a custom target path inside the container with --secret source=my_secret,target=/custom/path.
  3. Combine Docker secrets with a wrapper script that reads /run/secrets/ and exports them as environment variables for legacy apps.

Real-world use cases

  • Inject database credentials into a production Swarm service running PostgreSQL or MySQL — the password never touches the image.
  • Securely distribute TLS certificate private keys to a load-balanced NGINX service without embedding them in the build artifact.
  • Provide API keys to a microservice that consumes an external SaaS — rotate the key by creating a new secret and updating the service.

Key takeaways

  • Docker secrets require Swarm mode — even on a single node, run docker swarm init first.
  • Secrets are mounted as files at /run/secrets/<name> inside the container, never as environment variables by default.
  • Secrets are encrypted at rest on the manager and in transit, and they are never stored in image layers.
  • To update a secret, create a new one and use docker service update with --secret-rm and --secret-add.
  • Docker secrets are for small, sensitive blobs (<500 KB); use external secret managers for larger or dynamic secrets.
  • In Compose files for Swarm, define secrets as external: true and create them beforehand with docker secret create.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.