Как идиоматически обращаться к конфиденциальным данным при построении образа Docker?

Иногда при создании изображения Docker необходимо использовать конфиденциальные данные. Например, маркер API или ключ SSH для загрузки удаленного файла или для установки зависимостей из частного репозитория. Возможно, было бы желательно распределить полученное изображение и не учитывать конфиденциальные учетные данные, которые использовались для его создания. Как это можно сделать?

Я видел docker-squash, который может склеить несколько слоев в один, удалив любые удаленные файлы из окончательного изображения. Но есть ли более идиоматический подход?

Ответ 1

Что касается идиоматического подхода, я не уверен, хотя докер все еще довольно молод, чтобы иметь слишком много идиом.

У нас была такая же проблема в нашей компании. Мы пришли к следующим выводам, хотя это наши лучшие усилия, а не установленные лучшие практики докеров.

1) Если вам нужны значения во время сборки: поставьте файл свойств в контексте сборки со значениями, которые можно прочитать при сборке, затем файл свойств можно удалить после сборки. Это не так портативно, но будет выполнять эту работу.

2) Если вам нужны значения во время выполнения: передайте значения в качестве переменных среды. Они будут видны кому-то, у кого есть доступ к ps на коробке, но это может быть ограничено с помощью SELinux или других методов (честно говоря, я не знаю этого процесса, я разработчик, и операционные группы будут заниматься этой частью).

Ответ 2

К сожалению, до сих пор нет правильного решения для обработки конфиденциальных данных при создании образа докера.

У этой ошибки есть хорошее резюме того, что не так с каждым взломом, который предлагают люди: https://github.com/moby/moby/issues/13490

И большинство советов, похоже, путают секреты, которые нужно ввести в контейнер, с секретами, которые используются для создания контейнера, как некоторые из ответов здесь.

Текущие решения, которые кажутся действительно безопасными, все, кажется, сосредоточены вокруг записи секретного файла на диск или в память, а затем запуска небольшого глупого HTTP-сервера, а затем, когда процесс сборки извлекает секрет из http-сервера, используйте это, а не хранить его в изображении.

Лучшее, что я нашел, не переходя на этот уровень сложности, - это (не) использовать встроенную функцию предопределенных аргументов в docker compose files, как указано в этом комментарии:

https://github.com/moby/moby/issues/13490#issuecomment-403612834

Это, кажется, хранит секреты в истории построения изображений.

Ответ 3

Способ решения этой проблемы заключается в том, что у нас есть инструмент, написанный поверх docker build. После того, как вы начнете сборку с помощью этого инструмента, он загрузит файл докеров и изменяет его. Он изменяет все инструкции, требующие "секрет", например:

RUN printf "secret: asd123poi54mnb" > /somewhere && tool-which-uses-the-secret run && rm /somewhere

Однако это оставляет секретные данные доступным для всех, у кого есть доступ к изображению, если сам слой не удален с помощью инструмента, такого как docker-squash. Команда, используемая для создания каждого промежуточного уровня, может быть найдена с помощью команды истории

Ответ 4

Мэтью Закрывает об этом в в этой статье в блоге.

Подводя итог: вы должны использовать docker-compose для установки конфиденциальной информации в контейнер.

Ответ 5

2019 г., и я не уверен, что при использовании докера существует какой-то сомнительный подход или лучшие практики в отношении секретов: https://github.com/moby/moby/issues/13490 до сих пор остается открытым.


Секреты во время выполнения:

Пока что лучший подход, который я смог найти, это использование переменных среды в контейнере:

  • с опцией docker run -e... но тогда ваши секреты доступны в истории командной строки
  • с опцией docker env_file или docker-compose env_file. По крайней мере, секреты не передаются в командной строке
  • Проблема: в любом случае, теперь секреты доступны любому, кто может запускать команды Docker на вашем хосте Docker (используя команду docker inspect)

Секреты во время сборки (ваш вопрос):

Я вижу 2 дополнительных (частичных?) Решения этой проблемы:

Многоступенчатая сборка:

используйте многоэтапную сборку докера: в основном ваш файл docker определит 2 изображения:

  1. Одно первое промежуточное изображение ("изображение сборки"), в котором:

    • вы добавляете свои секреты к этому изображению: либо используйте build args, либо копируйте секретные файлы (будьте осторожны с arg для build: они должны быть переданы в командной строке docker build)
    • вы строите свой артефакт (теперь у вас есть доступ к вашему личному хранилищу)
  2. Второе изображение ("изображение распространения"), в котором:

    • вы копируете встроенный артефакт из "образа сборки"
    • распространять изображение в реестре докеров

Этот подход объясняется несколькими комментариями в цитируемой ветке github:

Внимание

Этот многоступенчатый подход к сборке далек от идеала: "образ сборки" все еще лежит на вашем хосте после команды сборки (и содержит вашу конфиденциальную информацию). Есть меры предосторожности, чтобы принять

Новая опция сборки --secret:

Я обнаружил этот вариант сегодня, и поэтому еще не экспериментировал с ним... Что я знаю до сих пор: