HxHippy

Secrets Management

Securely manage sensitive data in Docker containers.

Last updated: 2025-01-15

Docker Secrets

Securely manage sensitive data without exposing it in images or environment variables.

Why Not Environment Variables?

# Problems with env vars:
# 1. Visible in docker inspect
docker inspect container --format '{{json .Config.Env}}'

# 2. Visible in process listings
cat /proc/1/environ

# 3. Often logged accidentally

Docker Compose Secrets

# docker-compose.yml
services:
  api:
    image: myapi
    secrets:
      - db_password
      - api_key
    environment:
      # Tell app where to find secrets
      DB_PASSWORD_FILE: /run/secrets/db_password
      API_KEY_FILE: /run/secrets/api_key

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

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    file: ./secrets/api_key.txt

Reading Secrets in Application

// Node.js
const fs = require('fs');

function getSecret(name) {
  const file = process.env[`${name}_FILE`];
  if (file) {
    return fs.readFileSync(file, 'utf8').trim();
  }
  return process.env[name];
}

const dbPassword = getSecret('DB_PASSWORD');
# Python
import os

def get_secret(name):
    file_path = os.environ.get(f'{name}_FILE')
    if file_path:
        with open(file_path, 'r') as f:
            return f.read().strip()
    return os.environ.get(name)

db_password = get_secret('DB_PASSWORD')

BuildKit Secrets

For build-time secrets (not stored in image):

# syntax=docker/dockerfile:1
FROM node:20-alpine

# Mount secret at build time
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) \
    npm install
# Build with secret
DOCKER_BUILDKIT=1 docker build \
  --secret id=npm_token,src=./secrets/npm_token.txt \
  -t myapp .

External Secret Sources

secrets:
  # From file
  db_password:
    file: ./secrets/db_password.txt

  # External (pre-existing in Docker)
  api_key:
    external: true
    name: prod-api-key

  # From environment (for CI/CD)
  jwt_secret:
    environment: JWT_SECRET

Secrets Directory Structure

secrets/
  .gitignore          # Ignore everything in this dir
  db_password.txt
  api_key.txt
  jwt_secret.txt
# secrets/.gitignore
*
!.gitignore
!*.example

Secret Rotation

# Create versioned secrets
secrets:
  db_password_v2:
    file: ./secrets/db_password_v2.txt

services:
  db:
    secrets:
      - source: db_password_v2
        target: db_password

Best Practices

  1. Never commit secrets - Add to .gitignore
  2. Use _FILE suffix - Standardize secret file pattern
  3. Limit access - Only mount where needed
  4. Rotate regularly - Use versioned secrets
  5. Encrypt at rest - Use encrypted storage for files
intermediate Security Updated 2025-01-15
  • docker
  • secrets
  • credentials
  • passwords
  • security