Секреты в контейнерах
Почему ENV и build-арги текут, как правильно отдавать секреты контейнеру и BuildKit-секреты на сборке.
Где секреты текут
Контейнеру почти всегда нужен секрет: пароль базы, токен, ключ. Наивные способы их передать как раз и текут.
Секрет в образе. Если вшить пароль в Dockerfile (через ENV или
скопировать файл), он останется в слоях образа навсегда. Любой, кто
скачает образ, достанет секрет:
docker history --no-trunc myimage # видны команды сборки и ENV
Секрет в build-арге. ARG TOKEN на сборке тоже оседает в истории
образа. ARG не для секретов.
Правило: секрет не должен попадать в слои образа. Образ — это то, что раздают, в нём секретов быть не может.
Рантайм-секреты: переменные и файлы
Секрет отдают контейнеру при запуске, а не на сборке. Простой способ — переменная окружения:
docker run -e DB_PASSWORD="$DB_PASSWORD" myapp
Так секрет не в образе, а только в запущенном контейнере. Но и тут есть
нюанс: переменные окружения видны в docker inspect и наследуются
дочерними процессами. Для чувствительных секретов надёжнее отдавать их
файлом через примонтированный том или Docker secret, который кладётся в
/run/secrets/ и не светится в inspect:
# docker compose
services:
app:
secrets:
- db_password
secrets:
db_password:
file: ./db_password.txt
Приложение читает секрет из файла /run/secrets/db_password, а не из
переменной.
Секреты на этапе сборки: BuildKit
Иногда секрет нужен именно во время сборки: например, токен, чтобы скачать приватную зависимость. Класть его в ARG нельзя. Для этого есть BuildKit-секреты — секрет монтируется только на время одной команды и в слои не попадает:
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npmtoken \
NPM_TOKEN=$(cat /run/secrets/npmtoken) npm ci
docker build --secret id=npmtoken,src=./npm_token .
Секрет доступен только внутри этого RUN, после сборки его в образе нет.
Что важно запомнить
Образ раздают, поэтому секретов в его слоях быть не должно: вшитый ENV
или ARG виден в docker history.
Рантайм-секреты отдают при запуске: через -e (но видно в docker inspect) или, надёжнее, файлом/Docker secret в /run/secrets/.
Секрет, нужный на сборке, монтируют через BuildKit
(--mount=type=secret) — он доступен только в одной команде и в образ не
попадает.
В связке с ops-треком: для централизованного хранения секретов берут внешние хранилища (Vault) и sops, а контейнеру отдают уже в рантайме.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс