Docker Compose Secrets: Как да спрем да пишем пароли директно в docker-compose.yml

Docker Compose Secrets: Как да спрем да пишем пароли директно в docker-compose.yml

Всички сме го правили. Стартираш нов проект, трябва ти база данни, и пишеш нещо такова:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: mysupersecretpassword123

Работи. Правиш commit. Пускаш го в GitHub.

И ето — паролата ти за базата данни вече е публична. Завинаги. Дори да я изтриеш по-късно, тя живее в git историята.

В тази статия ще покажа три правилни начина за работа с чувствителни данни в Docker Compose — от простото към production-ready — за да не се налага никога повече да hardcode-ваш credentials.


Защо това е реален проблем

Преди да преминем към решенията, нека изясним за какво точно говорим.

Hardcode-натите secrets в docker-compose.yml са опасни, защото:

  • Git историята не забравя. Дори да премахнеш паролата в следващия commit, всеки с достъп до репото може да я намери в историята.
  • Мащабира се лошо. Един и същ файл се използва в dev, staging и production — с едни и същи credentials.
  • Нарушава 12-factor app принципа за строго разделение между конфигурация и код.
  • Е основният източник на изтичане на credentials в публични репозитории. GitHub сканира за подобни шаблони автоматично и ще те предупреди — но щетата вече е нанесена.

Метод 1: .env файлове (Бърза победа за разработка)

Най-простото подобрение. Вместо да hardcode-ваш стойности директно, ги реферираш като променливи.

Стъпка 1 — Създай .env файл:

# .env
POSTGRES_USER=myapp
POSTGRES_PASSWORD=много-по-сигурна-парола
POSTGRES_DB=production_db

Стъпка 2 — Реферирай го в docker-compose.yml:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}

Docker Compose автоматично чете .env от същата директория — без допълнителна конфигурация.

Стъпка 3 — Най-важната стъпка. Добави .env в .gitignore:

echo ".env" >> .gitignore

Предостави безопасен шаблон за екипа:

# .env.example  ← този файл commit-вай
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=

Предимства: Просто, без зависимости, работи навсякъде. ⚠️ Недостатъци: .env файлът все още стои като plaintext на диска. Добре за разработка, не е идеално за production.


Метод 2: Docker Secrets (Production-Ready)

Docker има вградена система за управление на secrets. Те се съхраняват криптирани в паметта и никога не се записват на диска или излагат като environment variables.

⚠️ Забележка: Docker Secrets в тази форма изискват инициализиран Docker Swarm mode. При single-node setup пак можеш да го използваш — просто изпълни docker swarm init веднъж.

Стъпка 1 — Създай secret-а:

# От низ
echo "моята-супер-секретна-парола" | docker secret create db_password -

# Или от файл
docker secret create db_password ./password.txt

Стъпка 2 — Реферирай го в docker-compose.yml:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: myapp
      POSTGRES_DB: production_db
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    external: true

Secret-ът се монтира като файл вътре в контейнера на /run/secrets/db_password. Много официални Docker images (PostgreSQL, MySQL, MariaDB) поддържат суфикса _FILE специално за този шаблон.

Стъпка 3 — Деплойни:

docker stack deploy -c docker-compose.yml myapp

Предимства: Secrets са криптирани в покой, никога не са в environment variables, идеално за production. ⚠️ Недостатъци: Изисква Swarm mode. Малко по-сложна настройка.


Метод 3: Secrets като локални файлове (Алтернатива без Swarm)

Ако не искаш да използваш Swarm mode, но все пак искаш secrets извън docker-compose.yml, можеш да монтираш файлове директно.

Стъпка 1 — Създай директория за secrets:

mkdir -p ./secrets
echo "моята-db-парола" > ./secrets/db_password.txt
echo "моята-redis-парола" > ./secrets/redis_password.txt

Стъпка 2 — Добави secrets директорията в .gitignore:

echo "secrets/" >> .gitignore

Стъпка 3 — Монтирай като read-only файлове в docker-compose.yml:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: myapp
      POSTGRES_DB: production_db
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - ./secrets/db_password.txt:/run/secrets/db_password:ro

  redis:
    image: redis:7-alpine
    command: sh -c 'redis-server --requirepass "$$(cat /run/secrets/redis_password)"'
    volumes:
      - ./secrets/redis_password.txt:/run/secrets/redis_password:ro

Предимства: Без Swarm, работи с обикновено docker compose up, secrets извън YAML. ⚠️ Недостатъци: Secret файловете все още стоят на диска — увери се, че хост машината е защитена.


Бонус: Провери дали не изтичаш secrets

Преди всеки commit, провери дали случайно не са попаднали secrets в YAML файла:

# Търси общи шаблони в compose файла
grep -Ei '(password|secret|key|token)\s*[:=]\s*[^\$\{]' docker-compose.yml

Ако тази команда върне резултат — имаш hardcode-нат secret. Оправи го преди да commit-ваш.

Можеш да добавиш това и като pre-commit hook, който автоматично блокира commit-а:

# .git/hooks/pre-commit
#!/bin/sh
if grep -Ei '(password|secret|key|token)\s*[:=]\s*[^\$\{]' docker-compose.yml; then
  echo "❌ Открит е възможен hardcoded secret в docker-compose.yml. Commit отменен."
  exit 1
fi

Направи го изпълним:

chmod +x .git/hooks/pre-commit

Кой метод да изберете?

СценарийПрепоръчан метод
Локална разработка.env файл + .gitignore
Production на един сървърЛокални secret файлове (Метод 3)
Multi-node / оркестриран productionDocker Secrets (Метод 2)
CI/CD pipelineEnvironment variables инжектирани от CI системата (GitHub Actions Secrets, GitLab CI Variables и др.)

Бърз чеклист преди да push-неш

  • Без plaintext пароли в docker-compose.yml
  • .env е в .gitignore
  • .env.example съществува и е commit-нат (с празни стойности)
  • secrets/ директорията е в .gitignore
  • Pre-commit hook-ът е настроен

Заключение

Hardcode-ването на пароли в docker-compose.yml е навик, в който лесно се попада и е трудно да се поправи след като репото е публично. Добрата новина е, че и трите метода по-горе са лесни за имплементиране — дори в съществуващ проект.

Започни с .env файлове още днес, ако не си го направил. Отнема пет минути и веднага елиминира най-честия източник на случайно изтичане на credentials.

open source spirit
🛠️
$

Намерихте материала за полезен?

Съдържанието на itpraktika.com е безплатно и ще остане такова.
Ако статията ти е помогнала — можеш да подкрепиш сайта с малка доброволна сума. Всяко дарение помага за поддръжката и развитието на портала.

PayPal Revolut

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *


Колко е 7 + 9 ? (въведете числото)