← Docker: продвинутое
11 мин · средне · Урок 2 из 3

Секреты в контейнерах

Почему 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, а контейнеру отдают уже в рантайме.

Прошли материал до конца? Отметьте урок пройденным.