lenec ru

← все посты

FastAPI dependency injection: паттерны для больших проектов

17K

Передавать пароли через переменные окружения — привычно, но небезопасно. Любой с доступом к docker inspect видит все env в открытом виде. Docker secrets решают проблему: секреты монтируются как файлы в tmpfs и не попадают ни в образ, ни в метаданные контейнера.

Проблема: env-переменные на виду

services:
  api:
    image: myapp
    environment:
      - DB_PASSWORD=super_secret_123
      - API_KEY=sk-live-abc123

Что не так:

  • docker inspect api покажет все значения в открытом виде
  • Переменные наследуются дочерними процессами и могут утечь в логи
  • Файл .env часто случайно попадает в git

Docker secrets: как работают

В Swarm секреты хранятся в зашифрованном Raft-логе. В обычном Compose v2+ механизм проще: секрет читается из файла на хосте и монтируется в контейнер по пути /run/secrets/<name> как read-only файл в tmpfs. Не видны в inspect, не наследуются процессами, хранятся в RAM.

Синтаксис в docker-compose.yml

services:
  api:
    image: myapp:latest
    secrets:
      - db_password
      - api_key

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

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

Секрет db_password читается из локального файла. С флагом external: true секрет должен быть создан заранее через docker secret create (только Swarm). Postgres поддерживает суффикс _FILE — читает значение из указанного пути.

Чтение секретов в приложении

Node.js:

import { readFileSync } from 'fs';

function getSecret(name: string): string {
  return readFileSync(`/run/secrets/${name}`, 'utf-8').trim();
}

const dbPassword = getSecret('db_password');
const apiKey = getSecret('api_key');

Python с fallback на env для локальной разработки:

from pathlib import Path
import os

def get_secret(name: str) -> str:
    path = Path(f"/run/secrets/{name}")
    if path.exists():
        return path.read_text().strip()
    return os.environ.get(name.upper(), "")

В проде читаем из secrets, локально — из .env.

Альтернативы

  • .env + chmod 600 — минимальная защита, только для dev
  • HashiCorp Vault — полноценный secrets manager с ротацией и аудитом
  • SOPS (Mozilla) — шифрует файлы секретов через AWS KMS / GCP KMS / PGP, можно хранить в git
  • Cloud-native — AWS Secrets Manager, GCP Secret Manager, Azure Key Vault

Best practices

  • Ротация: обновите файл секрета и пересоздайте контейнер. В Swarm — docker secret rm + docker secret create + redeploy
  • Least privilege: назначайте секрет только тем сервисам, которым он реально нужен
  • Аудит: логируйте доступ к секретам. Vault делает это из коробки
  • Не в образ: никаких COPY или ARG/ENV с секретами в Dockerfile. Только runtime-монтирование
  • gitignore: директория ./secrets/ в .gitignore, шаблон secrets/*.example для документации

Итог

Docker secrets — простой шаг от «пароли в env» к нормальной безопасности. Для production комбинируйте с Vault или облачным secrets manager. Главное: секрет не должен быть виден ни в inspect, ни в логах, ни в истории образа.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.