Docker Secrets: Don’t Expose Passwords via a Clumsy ‘inspect’ Command

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

Secure Your Passwords in 5 Minutes with Docker Secrets

You probably don’t want your database password showing up plainly in the system logs, right? Never throw API keys directly into the environment section of your docker-compose.yml file. Instead, use Docker Secrets to properly secure them, starting from your local environment.

Step 1: Create a file containing the password (e.g., db_password.txt). Remember to add this file to .gitignore immediately to avoid pushing it to public servers.

echo "my-super-secret-password" > db_password.txt

Step 2: Declaring secrets in docker-compose.yml is extremely simple:

services:
  db:
    image: postgres
    secrets:
      - db_password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    file: ./db_password.txt

Step 3: Run the command docker compose up -d and you’re done. Your password is now securely located at /run/secrets/db_password. If someone curiously runs docker inspect, they will only see a blank space instead of the actual password.

Environment Variables: A Bigger Loophole Than You Think

The truth is, with just one docker inspect <container_id> command, all your secrets will be visible to colleagues or anyone with server access. I’ve witnessed a system where all sensitive information was leaked because these environment variables were overwritten into the logs of a centralized monitoring tool.

Docker Secrets completely solves this problem through the following mechanisms:

  • Stored in RAM: In Docker Swarm, secrets are stored in an encrypted Raft log and only mounted into the container’s RAM (tmpfs) when needed. Data never touches the hard drive.
  • Access Control: Only specifically designated services have the right to ‘see’ that secret.
  • Centralized Management: Easily deploy the same configuration across multiple environments without worrying about mixing up data between Dev and Prod.

Actual Operating Mechanism

When you attach a secret to a service, Docker mounts it as a file in the /run/secrets/ directory inside the container. Most major images like MariaDB, Postgres, or WordPress have a built-in _FILE suffix option. This allows the application to read data directly from the file instead of from a standard environment variable.

Level Up Security with Docker Swarm

If you are operating a cluster with Docker Swarm, secret management becomes even more professional. All sensitive data is synchronized between Manager nodes via an encrypted mTLS channel with high security.

Pushing Secrets Directly from the CLI

You don’t need to create a physical file on the server. Push the value directly into Swarm’s database with a single command:

echo "serect_key_2024" | docker secret create api_key -

Deploying with Stack Deploy

In the stack.yml file, use the external keyword to leverage secrets that already exist on the system:

version: '3.8'
services:
  app:
    image: my-app:latest
    secrets:
      - api_key

secrets:
  api_key:
    external: true

Finally, deploy the system with the familiar command: docker stack deploy -c stack.yml my_web_app.

Lessons from the Field

Switching from docker-compose v1 to v2 provides a very smooth experience. In version 2 (using the docker compose command without a hyphen), the secrets feature has become a standard even if you aren’t running Swarm. You no longer need to use complex emulation tricks as before.

Writing More Flexible Code

To ensure the application runs well on both local and production, I often write a small Python function to prioritize reading the secret from a file before checking environment variables:

import os

def get_config(key, default=None):
    # Prioritize reading from Docker's secret path
    secret_path = f"/run/secrets/{key}"
    if os.path.exists(secret_path):
        with open(secret_path, 'r') as f:
            return f.read().strip()
    # Fallback to environment variables if the file is not found
    return os.getenv(key, default)

Don’t Let Secrets Expire (Secret Rotation)

Many people have the habit of using a single password for 2-3 years without changing it. With Docker Swarm, secrets are immutable, so you need to create a new version when updating. The standard process is: Create api_key_v2, update the compose file, redeploy so Docker automatically replaces the container, and finally delete api_key_v1 once everything is stable.

Checklist for Better Sleep

  • Never commit secret files: Always check .gitignore to ensure no .txt or .key files make it into Git.
  • Use Docker Configs where appropriate: For standard configuration files like nginx.conf, use configs instead of secrets for optimal performance.
  • Principle of Least Privilege: A Frontend container must never be allowed to access the database master’s secret.
  • Leverage RAM: Remember that in Swarm, secrets reside only in RAM. This protects data even if the physical hard drive of the server is compromised.

Security management isn’t hard; the key is to make it a daily habit. Good luck building systems that are both powerful and secure!

Share: