Недавно я экспериментировал с Docker над созданием некоторых сервисов для игры, и одна вещь, которая дергается, заключалась в том, чтобы вводить пароли в файл Docker. Я разработчик, поэтому хранение паролей в источнике кажется ударом в лицо. Должно ли это быть проблемой? Есть ли хорошие соглашения о том, как обрабатывать пароли в Dockerfiles?
Докер и защита паролей
Ответ 1
Определенно это проблема. Докер файлы обычно проверяются в хранилищах и совместно с другими людьми. Альтернативой является предоставление любых учетных данных (имена пользователей, пароли, токены, что-то чувствительное) как переменные среды во время выполнения. Это возможно с помощью аргумента -e
(для отдельных vars в CLI) или аргумента --env-file
(для нескольких переменных в файле) до docker run
.
Однако, env vars также не особенно безопасны. Они видны через docker inspect
, и, следовательно, они доступны любому пользователю, который может запускать команды docker
. (Конечно, любой пользователь, который имеет доступ к docker
на хосте, также имеет root.
Мой предпочтительный шаблон - использовать обертку script как ENTRYPOINT
или CMD
. Обертка script может сначала импортировать секреты из внешнего местоположения в контейнер во время выполнения, а затем выполнить приложение, предоставляя секреты. Точная механика этого зависит от вашей среды выполнения. В AWS вы можете использовать комбинацию ролей IAM, Служба управления ключами и S3 для хранения зашифрованных секретов в ведре S3. Что-то вроде HashiCorp Vault или credstash - еще один вариант.
AFAIK нет оптимального шаблона для использования конфиденциальных данных как части процесса сборки. На самом деле, у меня есть вопрос fooobar.com/questions/69320/... по этой теме. Вы можете использовать docker-squash для удаления слоев из изображения. Но для этой цели в Docker нет встроенных функций.
Вы можете найти shykes комментарии к конфигурации в контейнерах.
Ответ 2
Наша команда избегает размещения учетных данных в репозиториях, поэтому это означает, что они не разрешены в Dockerfile
. Наша лучшая практика в приложениях - использовать creds из переменных среды.
Мы решаем для этого с помощью docker-compose
.
Внутри docker-compose.yml
вы можете указать файл, содержащий переменные среды для контейнера:
env_file:
- .env
Обязательно добавьте .env
в .gitignore
, затем установите учетные данные в файле .env
, например:
SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd
Храните файл .env
локально или в безопасном месте, где остальная команда может его захватить.
Смотрите: https://docs.docker.com/compose/environment-variables/#/the-env-file
Ответ 3
Теперь Docker (версия 1.13 или 17.06 и выше) поддерживает управление секретной информацией. Здесь обзор и более подробная документация
Аналогичная функция существует в kubernetes и DCOS
Ответ 4
Вы никогда не должны добавлять учетные данные в контейнер, если только вы не в прямом эфире передаете кредиты тем, кто может загрузить изображение. В частности, выполнение и ADD creds
и более поздние RUN rm creds
не являются безопасными, поскольку файл creds остается в конечном изображении на промежуточном уровне файловой системы. Легко для любого, у кого есть доступ к изображению, чтобы извлечь его.
Типичное решение, которое я видел, когда вам нужны creds для зависимостей проверки, и это использовать один контейнер для сборки другого. I.e., как правило, у вас есть некоторая среда сборки в базовом контейнере, и вам нужно вызвать это для создания вашего контейнера приложений. Таким образом, простым решением является добавление вашего источника приложения, а затем RUN
команды сборки. Это небезопасно, если вам нужны кредиты в RUN
. Вместо этого вы помещаете ваш источник в локальный каталог, запустите (как в docker run
) контейнер, чтобы выполнить шаг сборки с локальным исходным каталогом, смонтированным в качестве тома, а кредиты либо вставляются, либо монтируются в качестве другого тома. Как только шаг сборки будет завершен, вы создадите свой последний контейнер простым ADD
в локальном исходном каталоге, который теперь содержит встроенные артефакты.
Я надеюсь, что Docker добавит некоторые функции, чтобы упростить все это!
Обновление: похоже, что метод, идущий вперёд, будет иметь вложенные сборки. Короче говоря, файл docker будет описывать первый контейнер, который используется для создания среды выполнения, а затем вторую вложенную сборку контейнера, которая может собрать все части в конечный контейнер. Таким образом, время сборки не находится во втором контейнере. Это приложение Java, где вам нужен JDK для создания приложения, но только JRE для его запуска. Обсуждается ряд предложений, лучше всего начать с https://github.com/docker/docker/issues/7115 и следовать некоторым ссылкам для альтернативных предложений.
Ответ 5
С помощью Docker v1.9 вы можете использовать команду ARG для получения аргументов, переданных командной строкой, в образ операции сборки. Просто используйте флаг - build-arg. Таким образом, вы можете избежать сохранения явного пароля (или другой разумной информации) в файле Docker и передать их на лету.
источник: https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg
Пример:
Dockerfile
FROM busybox
ARG user
RUN echo "user is $user"
команда сборки изображения
docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .
во время сборки распечатайте
$ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM busybox
---> c51f86c28340
Step 2 : ARG user
---> Running in 43a4aa0e421d
---> f0359070fc8f
Removing intermediate container 43a4aa0e421d
Step 3 : RUN echo "user is $user"
---> Running in 4360fb10d46a
**user is capuccino**
---> 1408147c1cb9
Removing intermediate container 4360fb10d46a
Successfully built 1408147c1cb9
Надеюсь, это поможет! Bye.
Ответ 6
В качестве альтернативы использованию переменных среды, которые могут быть беспорядочными, если у вас их много, заключается в использовании томов для создания каталога на хосте, доступном в контейнере.
Если вы поместите все свои учетные данные в виде файлов в этой папке, тогда контейнер может читать файлы и использовать их по своему усмотрению.
Например:
$ echo "secret" > /root/configs/password.txt
$ docker run -v /root/configs:/cfg ...
In the Docker container:
# echo Password is `cat /cfg/password.txt`
Password is secret
Многие программы могут считывать свои учетные данные из отдельного файла, поэтому таким образом вы можете просто указать программу на один из файлов.
Ответ 7
Мой подход, похоже, работает, но, вероятно, наивно. Скажи мне, почему это неправильно.
ARG, установленные во время сборки докеров, отображаются подкомандой истории, поэтому туда не нужно. Однако при запуске контейнера переменные среды, указанные в команде запуска, доступны контейнеру, но не являются частью изображения.
Итак, в Dockerfile выполните настройку, которая не включает секретные данные. Установите CMD что-то вроде /root/finish.sh
. В команде run используйте переменные окружения для отправки секретных данных в контейнер. finish.sh
использует переменные по существу для завершения задач сборки.
Чтобы упростить управление секретными данными, поместите его в файл, загруженный приложением docker с помощью переключателя --env-file
. Конечно, держите файл в секрете. .gitignore
и т.д.
Для меня finish.sh
запускает программу Python. Он проверяет, не запущен ли он раньше, затем завершает настройку (например, копирует имя базы данных в Django settings.py
).
Ответ 8
Пока я полностью согласен, нет простого решения. Там по-прежнему существует одна точка отказа. Либо файл докеров, и т.д., И так далее. У Apcera есть план, похожий на sidekick - двойная аутентификация. Другими словами, два контейнера не могут разговаривать, если не существует правила конфигурации Apcera. В своей демонстрации uid/pwd был в ясном виде и не мог использоваться повторно до тех пор, пока администратор не установил связь. Однако для работы это, вероятно, означало исправление Docker или, по крайней мере, сетевого плагина (если есть такая вещь).
Ответ 9
Существует новая команда docker [1] для управления секретами, но это работает только для кластеров рой.
docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver
Ответ 10
только время выполнения
docker-compose также обеспечивает решение без рой (поскольку v1.11: Секреты, использующие привязку привязок).
Секреты монтируются как файлы ниже /run/secrets/
с помощью docker-compose. Это решает проблему во время выполнения (запуск контейнера), но не во время сборки (создание изображения), потому что /run/secrets/
не монтируется во время сборки. Кроме того, это поведение зависит от запуска контейнера с компоновкой докеров.
Пример:
Dockerfile
FROM alpine
RUN cat /run/secrets/password
CMD sleep inifinity
Докер-compose.yml
version: '3.1'
services:
app:
build: .
secrets:
- password
secrets:
password:
file: password.txt
Чтобы выполнить, выполните:
docker-compose up -d
Дальнейшее чтение: