Moby: Перенаправить ключевой агент ssh в контейнер

Созданный на 13 июн. 2014  ·  190Комментарии  ·  Источник: moby/moby

Было бы неплохо иметь возможность перенаправить агент ключа ssh в контейнер во время run или build .
Часто нам нужно создать исходный код, который существует в частном репозитории, где доступ контролируется ключом ssh.

Добавление ключевого файла в контейнер - плохая идея, так как:

  1. Вы только что потеряли контроль над своим ключом ssh
  2. Ваш ключ, возможно, потребуется разблокировать с помощью ключевой фразы
  3. Ваш ключ может вообще не находиться в файле и доступен только через ключевой агент.

Вы можете сделать что-то вроде:

# docker run -t -i -v "$SSH_AUTH_SOCK:/tmp/ssh_auth_sock" -e "SSH_AUTH_SOCK=/tmp/ssh_auth_sock" fedora ssh-add -l
2048 82:58:b6:82:c8:89:da:45:ea:9a:1a:13:9c:c3:f9:52 phemmer<strong i="15">@whistler</strong> (RSA)

Но:

  1. Это работает только для docker run , но не для build .
  2. Это работает только в том случае, если демон докера работает на том же хосте, что и клиент.

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

aresecurity exintermediate kinfeature

Самый полезный комментарий

@ kienpham2000 , почему это решение не сохраняет ключ в слое изображения? Действия копирования и удаления ключа выполняются отдельными командами, поэтому существует слой, на котором должен быть ключ.
Наша команда до вчерашнего дня использовала ваше решение, но мы нашли улучшенное решение:

  • Мы генерируем предварительно подписанный URL-адрес для доступа к ключу с помощью aws s3 cli и ограничиваем доступ примерно на 5 минут, мы сохраняем этот предварительно подписанный URL-адрес в файл в каталоге репо, затем в dockerfile мы добавляем его к изображению.
  • В dockerfile у нас есть команда RUN, которая выполняет все эти шаги: используйте предварительный URL-адрес, чтобы получить ключ ssh, запустить npm install и удалить ключ ssh.
    Если выполнить это одной командой, ключ ssh не будет сохранен ни на каком уровне, но будет сохранен предварительно подписанный URL-адрес, и это не проблема, потому что URL-адрес станет недействительным через 5 минут.

Скрипт сборки выглядит так:

# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .

Dockerfile выглядит так:

FROM node

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    ssh -o StrictHostKeyChecking=no [email protected] || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]

Все 190 Комментарий

Интересно, даст ли # 6075 то, что вам нужно

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

+1 Я бы тоже нашел эту возможность полезной. В частности, при создании контейнеров, для которых требуется программное обеспечение, например, из частных репозиториев git. Я бы предпочел не делиться ключом репо в контейнере, а вместо этого хотел бы иметь возможность "docker build ..." использовать какой-то другой метод для получения доступа к разблокированным SSH-ключам, возможно, через запущенный ssh -агент.

+1. Я только начинаю знакомиться с Docker, и это был первый барьер, с которым я столкнулся. Я потратил некоторое время, пытаясь использовать VOLUME для монтирования auth sock, прежде чем понял, что докер не может / не может монтировать хост-том во время сборки.

Я не хочу, чтобы валялись копии SSH-ключа без пароля, и механика его копирования в контейнер с последующим его удалением во время сборки кажется неправильной. Я работаю в EC2 и даже не чувствую себя хорошо, копируя туда свои личные ключи (без пароля или без него).

Мой вариант использования - создание проекта Erlang с арматурой. Конечно, я мог бы клонировать первое репо и ДОБАВИТЬ его в образ с помощью файла Docker, но это не работает с частными зависимостями проекта. Думаю, я мог бы просто построить проект на хост-машине и ДОБАВИТЬ результат в новый образ Docker, но я бы хотел построить его в песочнице, которая называется Docker.

Вот некоторые другие люди, у которых есть такой же вариант использования: https://twitter.com/damncabbage/status/453347012184784896

Пожалуйста, примите SSH_AUTH_SOCK, это очень полезно.

Спасибо

Изменить: теперь, когда я знаю больше о том, как работает Docker (слои FS), невозможно сделать то, что я описал в отношении ДОБАВЛЕНИЯ ключа SSH во время сборки и его последующего удаления. Ключ все еще будет существовать в некоторых слоях FS.

+1, возможность использовать SSH_AUTH_SOCK будет очень полезна!

Я использую ключи SSH для аутентификации в Github, будь то частный репозиторий или публичный.

Это означает, что мои git clone команды выглядят так: git clone [email protected]:razic/my-repo.git .

Я могу смонтировать свой каталог хоста ~/.ssh в свои контейнеры во время docker run и ssh - все в порядке. Однако я не могу смонтировать свой ~/.ssh во время docker build .

: +1: для пересылки ssh во время сборки.

Насколько я понимаю, это неправильный путь. Правильный способ - создать образ докера на машине разработчика, а затем скопировать его на сервер докера.

@SevaUA - нет, это не так. Этот запрос связан с ограничением при выполнении docker build... . Вы не можете экспортировать переменную на этом этапе, как при выполнении docker run ... . Команда run позволяет экспортировать переменные в контейнер докера во время работы, тогда как сборка не позволяет этого. Это ограничение частично сделано намеренно, в зависимости от того, как dockerd работает при создании контейнеров. Но есть способы обойти это, и описанный вариант использования является допустимым. Таким образом, этот запрос пытается каким-то образом реализовать эту возможность в сборке.

Мне нравится идея # 6697 (секретное хранилище / хранилище), и это может сработать для этого, когда оно будет объединено. Но если это не сработает, альтернативой является использование прозрачного прокси-сервера для ssh. вне демона докера, перехватывая трафик демона докера (не внутри). В качестве альтернативы, все запросы git + ssh могут быть отправлены на какой-то локально определенный хост, который прозрачно проксирует github или все, что вам в конечном итоге нужно.

Эта идея уже высказывалась (см. Комментарий 2). Это не решает проблему.

+1 за пересылку ssh во время сборки.

+1 при переадресации агента SSH на docker build

+1 для пересылки ssh во время сборки для подобных npm install или аналогичных.

У кого-нибудь работает переадресация ssh во время работы на OSX? Я задал вопрос: http://stackoverflow.com/questions/27036936/using-ssh-agent-with-docker/27044586?noredirect=1#comment42633776_27044586 похоже, что это невозможно с OSX ...

+1 = (

Просто нажмите и на это препятствие. Попытка запустить npm install указывает на частное репо. настройка выглядит так:
host -> vagrant -> docker может ssh-agent переслать host -> vagrant -! docker

+1
Просто нажмите это, пытаясь выяснить, как заставить ssh-агент работать во время сборки докера.

+1 так же, как и предыдущие ребята. Кажется, лучшее решение этой проблемы при необходимости доступа к одному или нескольким частным репозиториям git (например, bundle install и npm install ) при создании образа Docker.

Я могу смонтировать свой каталог host ~ / .ssh в мои контейнеры во время запуска докера, и ssh все в порядке.

@razic Не могли бы вы рассказать, как у вас это работает? Потому что, когда я пробовал это раньше, он жаловался на "Плохого владельца или разрешения"

Если вы не убедитесь, что все контейнеры работают с определенным пользователем или разрешениями, которые позволяют вам это делать?

+1 к SSH_AUTH_SOCK

@tonivdv взгляните на команду docker run в начальном комментарии по этой проблеме. Он связывает путь, на который указывает SSH_AUTH_SOCK к /tmp/ssh_auth_sock внутри контейнера, а затем устанавливает SSH_AUTH_SOCK в контейнере на этот путь.

@ md5 Я предполагаю, что @razic и @tonivdv говорят о монтировании следующим образом: -v ~/.ssh:/root/.ssh:ro , но когда вы делаете это, файлы .ssh не принадлежат root и, следовательно, не проходят проверки безопасности.

@KyleJamesWalker да, это то, что я понял из @razic, и это была одна из моих попыток некоторое время назад, поэтому, когда я прочитал, что @razic смог заставить его работать, мне было интересно, как :)

@tonivdv Я также хотел бы знать, возможно ли это, но я ничего не нашел, когда пытался в последний раз.

+1 Мне интересно создавать одноразовые среды разработки с использованием Docker, но я не могу заставить его работать. Это очень поможет в этом отношении.

Для тех, кто ищет временное решение, у меня есть исправление, которое я использую, в котором используются грубые силы:

https://github.com/atrauzzi/docker-laravel/blob/master/images/php-cli/entrypoint.sh

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

@atrauzzi интересный подход. Для нашей среды разработки мы создаем базовый образ и копируем ключ ssh прямо в него. Его преимущество заключается в том, что его не нужно предоставлять при каждом запуске. И каждое изображение, унаследованное от этого мага по умолчанию, также имеет в себе ключ. Однако с нашим способом вы, очевидно, не можете делиться этим публично; p

+1 это было бы здорово

@tonivdv Контейнер, для которого создан сценарий, часто создается и уничтожается, поскольку это просто хост для инструментов CLI. Вы, конечно, можете проделать операцию только один раз. Но если кто-то изменяет свои настройки и повторно запускает команду через контейнер, каждый раз это должна быть новая копия.

@atrauzzi Я понимаю. Ваш подход должен быть принят образами докеров, для которых может потребоваться закрытый ключ ssh. Например, изображение композитора должно включать ваш сценарий точки входа в случае частных репозиториев. По крайней мере, до тех пор, пока у докера не появится собственное решение.

: +1: для пересылки ssh через сборку

Обязательно здесь!

@atrauzzi В настоящее время я использую другой подход, который мне очень нравится. Он создает контейнер тома данных с содержимым ssh. Если вы хотите использовать свои ssh-ключи в другом контейнере, я могу просто использовать это с помощью следующей команды:

docker run -ti --volumes-from ssh-data ...

Таким образом, вам не нужно ставить точку входа для каждого изображения, и он может работать со всеми изображениями.

Чтобы создать этот контейнер, я делаю следующее

docker run \
  --name ssh-data \
  -v /root/.ssh \
  -v ${USER_PRIVATE_KEY}:/root/.ssh/id_rsa \
  busybox \
  sh -c 'chown -R root:root ~/.ssh && chmod -R 400 ~/.ssh'

Надеюсь, это поможет другим :)

Ваше здоровье

@tonivdv - Я

@atrauzzi Ага, я понимаю. При этом пользователь должен правильно поддерживать свой контейнер тома ssh. При необходимости он может использовать даже другие. И при желании его можно сгенерировать на лету с помощью скрипта. Но я не думаю, что есть одно-единственное хорошее решение. Все зависит от потребностей. Просто хотел поделиться, чтобы другие могли выбрать решение, исходя из своих потребностей. Надеюсь вскоре написать об этом в блоге, и я тоже с нетерпением жду вашего решения! Ваше здоровье

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

@atrauzzi Это правда, что контейнер тома должен быть там, но, по-вашему, пользователь тоже должен поделиться своим ssh-ключом при запуске, верно? Таким образом, помимо необходимости в контейнере тома ssh, единственная разница в обоих решениях с точки зрения работы заключается в следующем:

docker run ... --volumes-from ssh-data ... php-cli ...

и

docker run ... -v ~/.ssh:/path/.host-ssh ... php-cli ..

правильно? Или мне что-то еще не хватает :)

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

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

Ваше здоровье

Было бы действительно здорово получить обновленную информацию от команды Docker о статусе этой функции. В частности, аутентификация SSH от docker build .

Это уже приближается к 1 году. Довольно удивительно, учитывая практичность реальных случаев использования для этого. В настоящее время мы динамически генерируем изображения, фиксируя запущенные контейнеры. У нас не может быть Dockerfile в репозитории нашего приложения. Это прерывает поток практически всего. Я не могу использовать свое приложение с какими-либо службами Docker, такими как Compose или Swarm, пока проблема не будет решена.

Обновление будет очень признательно. Пожалуйста и спасибо.

/ cc @phemmer

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

@jfrazelle

Я знаю, что вы, ребята, нас не игнорируете :)

Итак, статус:

Мы рассмотрим возможность реализации этого предложения, если будет принято предложение.
и инженерная пропускная способность.

Это звучит правильно для вас?

Кроме того, есть ли в настоящее время какие-либо открытые предложения по решению этой проблемы?

Во вторник, 7 апреля 2015 г., Джесси Фразель [email protected] написала:

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

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90737847.

Мы рассмотрим возможность реализации этого предложения, если будет принято предложение.
и инженерная пропускная способность.

да

И я не думаю, что по этому поводу есть какие-то открытые предложения.

Во вторник, 7 апреля 2015 г., в 14:36, Захари Адам Каплан <
[email protected]> написал:

@jfrazelle

Я знаю, что вы, ребята, нас не игнорируете :)

Итак, статус:

Мы рассмотрим возможность реализации этого предложения, если будет принято предложение.
и инженерная пропускная способность.

Это звучит правильно для вас?

Кроме того, есть ли в настоящее время какие-либо открытые предложения по решению этой проблемы?

Во вторник, 7 апреля 2015 г., Джесси Фразель [email protected]
написал:

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

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90737847.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90738913.

Я не знаю, что я слишком упрощаю, но вот мое предложение:

SSHAGENT: вперед # по умолчанию игнорировать

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

У меня нет опыта работы с кодовой базой докеров, но это достаточно важно для меня, и я бы подумал о том, чтобы взяться за это.

Здорово. Где я могу узнать, как подать предложение? Есть ли
конкретное руководство или я должен просто открыть вопрос?

Во вторник, 7 апреля 2015 г., Джесси Фразель [email protected] написала:

Мы бы рассмотрели возможность реализации этого, если бы была принята
предложение
и инженерная пропускная способность.

да

И я не думаю, что по этому поводу есть какие-то открытые предложения.

Во вторник, 7 апреля 2015 г., в 14:36, Захари Адам Каплан <
[email protected]
<_e i = "18">

@jfrazelle

Я знаю, что вы, ребята, нас не игнорируете :)

Итак, статус:

Мы бы рассмотрели возможность реализации этого, если бы была принята
предложение
и инженерная пропускная способность.

Это звучит правильно для вас?

Кроме того, есть ли в настоящее время какие-либо открытые предложения по решению этой проблемы?

Во вторник, 7 апреля 2015 г., Джесси Фразель < [email protected]
<_e i = "31" /> написал:

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

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90737847.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90738913.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90739596.

Я имею в виду предложение дизайна
https://docs.docker.com/project/advanced-contributing/#design -proposal

Во вторник, 7 апреля 2015 г., в 14:39, Даниэль Штаудигель [email protected]
написал:

Я не знаю, что я слишком упрощаю, но вот мое предложение:

SSHAGENT: вперед # по умолчанию игнорировать

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

У меня нет опыта работы с кодовой базой докеров, но это
достаточно важен для меня, чтобы я подумал о том, чтобы взять его на себя.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90739803.

Это действительно высокоуровневая идея, но что, если вместо подключения через удаленный api докера, докер запустит демон инициализации со встроенным демоном ssh внутри контейнера?

Это можно использовать для решения ряда проблем.

  • Этим демоном будет PID 1, а основным процессом контейнера будет PID 2. Это решит все проблемы с игнорированием сигналов PID 1 и некорректным завершением работы контейнеров. (# 3793)
  • Это позволит чисто пересылать ключевой агент SSH. (# 6396)
  • Этот демон может держать пространства имен открытыми (# 12035)
  • TTY будет создан демоном (# 11462)
  • ... и, вероятно, многие другие проблемы, которые я забываю.

вы можете захотеть увидеть https://github.com/docker/docker/issues/11529 о
первый пункт списка

Во вторник, 7 апреля 2015 г., в 14:46, Патрик Хеммер [email protected]
написал:

Это действительно высокоуровневая идея, но что, если вместо того, чтобы прикреплять
удаленный api докера, докер запустил демон инициализации со встроенным ssh
демон, внутри контейнера?

Это можно использовать для решения ряда проблем.

  • У этого демона будет PID 1, а основным процессом контейнера будет
    PID 2. Это решит все проблемы с игнорированием сигналов PID 1 и
    контейнеры не закрываются должным образом. (# 3793
    https://github.com/docker/docker/issues/3793)
  • Это позволит чисто пересылать ключевой агент SSH. (# 6396
    https://github.com/docker/docker/issues/6396)
  • Этот демон может держать открытыми пространства имен (# 12035
    https://github.com/docker/docker/issues/12035)
  • TTY будет создан демоном (# 11462
    https://github.com/docker/docker/issues/11462)
  • ... и, вероятно, многие другие проблемы, которые я забываю.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90741192.

11529 совершенно не имеет отношения к проблеме PID 1.

Стреляй, черт возьми, копировальная паста, теперь мне нужно снова найти другого

нет, это тот, он исправляет зомби-вещи PID 1, о которых я думал, что вы имели в виду, но независимо от того, что я просто публиковал, поскольку его intestesting - это все

@phemmer Похоже, у вас есть опыт, который

Также похоже, что @dts, и я готов потратить время на работу над этим.

@phemmer и @dts, есть ли какой-либо способ перенести это обсуждение в немного более

@phemmer Похоже, у вас есть опыт, который

К сожалению, не совсем :-)
Я могу выдвигать идеи дизайна, но я знаю лишь небольшие части базы кода докеров. Этот тип изменений, вероятно, будет крупномасштабным.

Здесь уже было несколько предложений:

@phemmer предложил

что, если вместо подключения через удаленный api докера, докер запустит демон инициализации со встроенным демоном ssh внутри контейнера?

@dts предложил

SSHAGENT: вперед # по умолчанию игнорировать
Если установлено, во время сборки сокет и связанные переменные среды подключаются к контейнеру, где их можно использовать. Механические части этого уже существуют и работают, просто вопрос их соединения в сборке докера.

@razic предложил

Включить привязку тома для docker build .

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

@jfrazelle Есть идеи, как перейти к следующему шагу? На самом деле я просто пытаюсь это сделать. Понятно, что в этом есть большой интерес. Я готов отстаивать эту функцию, доведя ее до конца.

Я могу присутствовать на совещании по slack / irc / Gchat / и т. Д., Я думаю, что это немного упростит задачу, по крайней мере, для сбора требований и принятия решения о разумном порядке действий.

@dts предложил

SSHAGENT: вперед # по умолчанию игнорировать

Это просто идея о том, как это будет потребляться, а не реализовано. «Демон init / ssh» - это идея, как это будет реализовано. Оба могут существовать.

@razic предложил

Включите привязку тома для запуска докера.

К сожалению, это не сработает. Предполагая, что это означало docker build , а не docker run , который уже поддерживает монтирование томов, клиент может быть удаленным (один из ярких примеров - boot2docker). Привязка тома работает только тогда, когда клиент находится на том же хосте, что и демон докера.

@razic, пожалуйста, перейдите по этой ссылке о предложении по дизайну ... это не предложения https://docs.docker.com/project/advanced-contributing/#design -proposal

@phemmer

Я не понимаю, почему это не сработает. docker-compose работает с монтированием тома против кластера swarm . Если файл / папка не находится в хост-системе, он ведет себя так же, как если бы вы запустили -v с несуществующим путем.

@jfrazelle Понятно .

Если файл / папка не находится в хост-системе, он ведет себя так же, как если бы вы запустили -v с путем, которого нет в локальном докере.

Я не уверен, что понимаю вашу точку зрения. Как такое поведение помогает решить эту проблему?
Если у меня есть агент ключа ssh, который прослушивает /tmp/ssh-UPg6h0 на моем локальном компьютере, и у меня есть докер, работающий на удаленном компьютере, и вызывается docker build , этот локальный агент ключа ssh недоступен для демон докера. При монтировании тома этого не произойдет, а контейнеры docker build не будут иметь доступа к ключу ssh.

На высоком уровне я вижу только 2 способа решить эту проблему:

1. Прокси-сервер сокета агента ключа ssh:

Демон docker создает сокет домена unix внутри контейнера, и всякий раз, когда к нему что-то подключается, он передает это соединение обратно клиенту, который на самом деле выполняет команду docker build .

Это может быть сложно реализовать, поскольку внутри контейнера может быть произвольное количество подключений к этому сокету домена unix. Это будет означать, что демон и клиент докера должны проксировать произвольное количество подключений или демон должен иметь возможность говорить по протоколу агента ssh и мультиплексировать запросы.

Однако теперь, когда удаленный API докеров поддерживает веб-сокеты (в то время, когда эта проблема создавалась, этого не было), это может быть не слишком сложно.

2. Запустите настоящий демон SSH.

Вместо того, чтобы взламывать ssh-агент, используйте реальное ssh-соединение от клиента к контейнеру. Докер-клиент будет либо иметь в комплекте ssh-клиент, либо вызывать ssh в удаленном контейнере.
Это будет гораздо более масштабное изменение, поскольку оно заменит способ прикрепления к контейнерам. Но это также избавит докера от необходимости справляться с этим и перейти на стандартные протоколы.
Это также может решить другие проблемы (как упоминалось здесь ).

Так что, в конечном итоге, изменение будет намного более масштабным, но может быть более правильным решением.
Хотя реально, из-за масштаба, я сомневаюсь, что это произойдет.

@phemmer

Я не уверен, что понимаю вашу точку зрения. Как такое поведение помогает решить эту проблему?

Потому что наиболее распространенный вариант использования - это люди, создающие образы с зависимостями, которые размещаются в частных репозиториях, требующих аутентификации SSH.

Вы создаете образ на машине с ключом SSH. Так просто.

Если у меня есть агент ключа ssh, который прослушивает / tmp / ssh-UPg6h0 на моем локальном компьютере, и у меня есть докер, работающий на удаленном компьютере, и вызывается сборка докера, этот локальный агент ключа ssh недоступен для демона докера.

Я знаю. Какая разница? Я буду запускать docker build на машине, у которой есть доступ к сокету аутентификации.

Я пытаюсь сказать ... docker-compose позволяет вам использовать команду громкости против кластера swarm , независимо от того, находится файл на самом деле на хосте или нет! .

Мы должны сделать то же самое для монтирования томов в сборках докеров.

| Файл находится в системе | Действие |
| : - | : - |
| Да | Крепление |
| Нет | Нет (на самом деле он пытается смонтировать, но создает пустую папку, если файл / папка не существует, вы можете проверить это, запустив docker run -v /DOES_NOT_EXIST:/DOES_NOT_EXIST ubuntu ls -la /DOES_NOT_EXIST ) |

Одна из концепций swarm - сделать модель с несколькими хостами прозрачной.

Хорошо, что мы думаем об удаленном докере, но это не имеет особого значения.

Мы должны просто скопировать поведение для монтирования тома для docker build точно так же, как мы делаем для docker run .

С https://github.com/docker/compose/blob/master/SWARM.md :

Главное, что мешает беспроблемной работе многоконтейнерных приложений в Swarm, - это заставить их общаться друг с другом: включение частной связи между контейнерами на разных хостах не было решено без взлома.

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

@phemmer Я думаю, что люди, вероятно, думают о решении описанной вами проблемы. Проблема, которую вы описываете, звучит как https://github.com/docker/docker/issues/7249, который является отдельным.

Если мы воспользуемся моим подходом: просто разрешить монтирование тома в сборке докеров (независимо от того, действительно ли файл, который вы пытаетесь смонтировать, находится в системе , то мы можем закрыть эту проблему. И начать работу над https://github.com/ docker / docker / issues / 7249, который расширил бы поведение этой функции на работу с удаленными демонами докеров, у которых нет локального файла.

@ cpuguy83 Перед тем, как создать предложение, я посмотрел на № 7133 и заметил, что он выглядит напрямую связанным.

Не могли бы вы просто добавить сюда несколько слов? На самом деле № 7133 связан с моим предложением по исправлению этой проблемы, которое заключается в том, чтобы разрешить docker build поддерживать тома.

@razic Это связано с тем, что VOLUME /foo самом деле создает том и монтирует его в контейнер во время сборки, что обычно нежелательно.

Я бы также сказал, что предложение, основанное на использовании bind-mounts для загрузки файлов в контейнеры сборки, вероятно, не сработает.
См. №6697

Запуск -v с docker build может иметь другой путь выполнения кода.
Вместо того, чтобы создавать том и монтировать его во время сборки, мы можем сохранить
текущее поведение, при котором тома в файлах докеров не упоминаются. И
вместо этого действуйте только на -v при запуске с аргументами CLI.

В среду, 8 апреля 2015 г., Брайан Гофф [email protected] написал:

@razic https://github.com/razic Это в связи с тем, что VOLUME
/ foo фактически создает том и монтирует его в контейнер во время
строить, что вообще нежелательно.

Я бы также сказал предложение, основанное на использовании bind-mounts для загрузки файлов в
строить контейнеры наверное летать не собираюсь.
См. # 6697 https://github.com/docker/docker/pull/6697

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment -90905722.

@ cpuguy83 Спасибо за разъяснения.

6697 Также не будет летать, так как он уже закрыт, а №10310 практически обманывает №6697.

+1, я только что нажал на это сегодня, пытаясь создать образ для приложения Rails, которое использует Bower для установки клиентских зависимостей. Бывает, что одна из зависимостей указывает на [email protected]:angular/bower-angular-i18n.git и поскольку git терпит неудачу, bower терпит неудачу, и создание образа тоже терпит неудачу.

Кстати, мне очень нравится то, что делает бродяга. С помощью единственной конфигурации forward_agent в Vagrantfile это решено для бродячих гостей. Мог ли Docker реализовать что-то подобное?

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

Мое обходное решение состояло в том, чтобы сгенерировать новую пару ключей RSA, настроить ключ pub на github (добавить отпечаток пальца) и добавить закрытый ключ в образ Docker:

ADD keys/docker_rsa /srv/.ssh/id_rsa

Я бы хотел избежать этого, но я думаю, что пока это приемлемо. Любые другие предложения приветствуются!

Я не уверен, кто убил больше щенков. Вы за это или Docker за то, что пока не предоставили вам лучший способ.

В любом случае, наверное, в эти выходные я подам предложение. @ cpuguy83 правильно, что люди хотя бы думают об этом и обсуждают возможные решения. Так что на данный момент это просто вопрос того, что мы договорились о чем-то и заставили кого-то поработать над этим. Я полностью готов поработать над этим, поскольку в настоящее время это одна из моих самых больших проблем с Docker.

@razic Это довольно распространенный вариант использования, поэтому спасибо, что

@fullofcaffeine Я не на 100% уверен, как Docker работает изнутри, но я думаю, что если это не делается с помощью одной команды RUN (что невозможно с вашим обходным путем), история образа поддерживает SSH-ключ.

@razic хороший момент.

Чтобы обойти это ограничение, мы поиграли с идеей загрузки закрытых ключей (с локального HTTP-сервера), выполнения команды, которая требует ключей, а затем их удаления.

Поскольку мы делаем все это в одном RUN , ничего не кэшируется в изображении. Вот как это выглядит в Dockerfile:

RUN ONVAULT npm install --unsafe-perm

Наша первая реализация вокруг этой концепции доступна по адресу https://github.com/dockito/vault.

Единственный недостаток - наличие запущенного HTTP-сервера, поэтому сборка Docker-хаба не выполняется.

Дайте мне знать, что вы думаете :)

+1
хотелось бы, чтобы это реализовано, это помогло бы настроить контейнеры для среды разработки

+1, просто нужно перенаправить ssh-agent с boot2dock

Чтобы обойти это ограничение, мы сделали трехэтапный процесс:

  1. построить docker-контейнер без SSH-требуемых зависимостей, добавив исходный код на последнем шаге
  2. смонтировать источник через общий том, плюс SSH_AUTH_SOCK через общий том и запустить этап сборки, записывая требуемый ssh ​​вывод (скажем, рубиновые драгоценные камни, размещенные на github) обратно в общий том
  3. повторно запустить сборку докеров, которая повторно запустит добавление источника, поскольку драгоценные камни теперь находятся в исходном каталоге

Результатом является образ докера с зависимостями, полученными через SSH-auth, в котором никогда не было ключа SSH.

Я создал сценарий для включения переадресации агента ssh для docker run в среде boot2docker на OSX с минимальными хлопотами. Я знаю, что это не решает проблему сборки, но может быть полезно для некоторых:

https://gist.github.com/rcoup/53e8dee9f5ea27a51855

Работает ли ключевой агент Forward ssh с такими сервисами, как Amazon EC 2 Container service? Мне кажется, что для этого потребуется определенное программное обеспечение, которое может быть доступно не на всех платформах или PaaS, которые вы используете для развертывания своих контейнеров.

Требуется более общее решение, подходящее для всех.

В настоящее время я использую переменные среды. Сценарий bash получает переменную закрытого ключа (и известных хостов) и распечатывает ее в файлы id_rsa и known_hosts. Это работает, но мне еще предстоит оценить последствия такого решения для безопасности.

FWIW, я обнаружил, что контейнерный ssh-агент и совместное использование томов хорошо работают с минимальной глупостью:

https://github.com/whilp/ssh-agent

Хотя было бы здорово получить для этого первоклассную поддержку.

Важно различать, что работает в _run_ и _build_. Решение @whilp прекрасно работает в _run_, но не работает в _build_, потому что вы не можете получить доступ к другим томам докеров во время _build_. Вот почему этот билет до сих пор остается открытой болезнью.

@rvowles ага , согласен. Я собрал что-то вместе для создания контейнеров с помощью последовательности вызовов run / commit (то есть без файлов Docker); это имело смысл для моего конкретного случая использования, но общая поддержка (включая время сборки) для чего-то вроде пересылки агентов была бы очень полезной.

Включены ли IP-адреса для запущенных контейнеров в / etc / hosts во время сборки? Если это так, одним из решений может быть запуск контейнера, который обслуживает ключи, а затем его скручивание во время сборки.

Возможно, вам будет интересно узнать, что я писал в блоге о способе использования вашего SSH-агента во время docker build - http://aidanhs.com/blog/post/2015-10-07-dockerfiles-reproducibility- обман / # _ streamlining_your_experience_using_an_ssh_agent

Вам просто нужно запустить единственный контейнер. После запуска доступ к агенту SSH должен работать безупречно, всего с 3 дополнительными строками в вашем Dockerfile - больше не нужно предоставлять свои ключи контейнеру.

Некоторые предостережения: вам нужен Docker> = 1.8, и он не будет работать с автоматической сборкой Docker Hub (очевидно). Также прочтите примечание о безопасности! Не стесняйтесь поднимать вопросы в репозитории sshagent github, на который я ссылаюсь в сообщении, если у вас есть какие-либо проблемы.

Я также решил эту проблему аналогично @aidanhs - вытащив требуемый секрет через локальную подсеть
https://github.com/mdsol/docker-ssh-exec

Есть ли прогресс в том, чтобы сделать это возможным? Я не могу связать-смонтировать каталог ~/.ssh хоста, потому что разрешения и права собственности перепутаны.

Разве это не было бы решено, если разрешить привязку монтирования для принудительного использования определенных uid / gid и разрешений?

@atrauzzi bind-
Это можно сделать через FUSE (например, bindfs), но не только с помощью обычных привязок.

@ cpuguy83 Это действительно начинает уводить меня по дорогам, с

Здесь нет удобного варианта? У меня такое ощущение, что здесь есть проблема, которую просто откладывают.

@atrauzzi Действительно, решить эту проблему в ближайшем будущем непросто (во всяком случае, не без проблем).

+1 это большой блокировщик для простого Dockerfile приложения Node.js. Я работал над многими приложениями Node и редко видел одно, у которого нет частного репозитория Github в качестве зависимости NPM.

В качестве обходного пути @apeace вы можете попробовать добавить их как подмодули git в .git в каждом из них. В сборке докеров их можно просто установить из локального каталога. Если по какой-то причине они должны быть полноценными репозиториями git, убедитесь, что файл .git отсутствует в сборке докера, и добавьте .git/modules/<repo> как <path>/<repo>/.git . Это гарантирует, что они являются обычными репозиториями, как если бы они были клонированы.

Спасибо за это предложение @jakirkham , но мы так долго использовали частные репозитории в качестве зависимости NPM, я не хочу нарушать нормальный рабочий процесс npm install .

На данный момент у нас есть решение, которое работает, но просто неприятно. У нас есть:

  • Создал пользователя и команду Github, у которых есть доступ только для чтения к репозиториям, которые мы используем в качестве зависимостей NPM.
  • Зафиксировал закрытый ключ этого пользователя в нашем репо, где у нас есть наш Dockerfile
  • В Dockerfile вместо RUN npm install мы делаем RUN GIT_SSH='/code/.docker/git_ssh.sh' npm install

Где git_ssh.sh - это сценарий вроде этого:

#!/bin/sh
ssh -o StrictHostKeyChecking=no -i /code/.docker/deploy_rsa "$@"

Это работает, но пересылка ключевого агента ssh была бы намного приятнее и потребовала бы гораздо меньше усилий по настройке!

: +1:
Не могу поверить, что этот запрос функции все еще не реализован, поскольку существует множество случаев использования, когда людям требуется доступ из частных репозиториев во время сборки.

Я пытаюсь создавать контейнеры для различных сред разработки встроенных систем, которым требуется доступ к частным репозиториям. Добавление поддержки ключей ssh ​​хоста было бы отличной функцией. Самые популярные методы, летающие на SO и других страницах, небезопасны, и до тех пор, пока не будет поддержки для этих функциональных слоев, будут распространяться закрытые ключи.

: +1:

: +1: Мне это нужно было вечно.

Привет, @apeace , я не знаю, видели ли вы это, но я уже говорил ранее о нашем способе решения этой проблемы.

Это комбинация скрипта и веб-сервера. Как вы думаете, https://github.com/dockito/vault ?

@pirelenito, разве это не сделает ключ доступным на уровне сборки? Если это так, то нам не стоит добавлять Dockito Valut в наш процесс сборки - мне это кажется таким же «дженки», как и то, что мы делаем сейчас. Я ценю предложение!

@apeace сценарий ONVAULT загружает ключи, запускает вашу команду и сразу же удаляет ключи. Поскольку все это происходит в одной команде, последний слой не будет содержать ключ.

@apeace В Medidata мы используем созданный нами крошечный инструмент под названием docker-ssh-exec . В результирующем образе сборки остается только двоичный файл docker-ssh-exec - никаких секретов. И для этого требуется всего лишь одно слово изменить Dockerfile , так что это очень "мало места".

Но если вам _ действительно_ нужно использовать решение только для докеров, теперь есть встроенный способ сделать это, как указано в сообщении блога компании . Docker 1.9 позволяет использовать параметр --build-arg для передачи эфемерных значений процессу сборки. Вы должны иметь возможность передать закрытый SSH-ключ как ARG , записать его в файловую систему, выполнить git checkout , а затем _delete_ ключ, все в пределах одного RUN Директива docker-ssh-exec ). Это сделает уродливую Dockerfile , но не требует внешних инструментов.

Надеюсь это поможет.

@benton Мы придумали похожее решение. :)

Спасибо @pirelenito и @benton , я рассмотрю все ваши предложения!

РЕДАКТИРОВАТЬ : на самом деле следующее _НЕ_ безопасно:

Для записи, вот как вы проверяете частное репо из Github, не оставляя свой SSH-ключ в полученном изображении.

Сначала замените user/repo-name в следующем Dockerfile на путь к вашему частному репо (убедитесь, что вы сохранили префикс [email protected] чтобы ssh использовался для проверки):

FROM ubuntu:latest

ARG SSH_KEY
ENV MY_REPO [email protected]:user/repo-name.git

RUN apt-get update && apt-get -y install openssh-client git-core &&\
    mkdir -p /root/.ssh && chmod 0700 /root/.ssh && \
    ssh-keyscan github.com >/root/.ssh/known_hosts

RUN echo "$SSH_KEY" >/root/.ssh/id_rsa &&\
    chmod 0600 /root/.ssh/id_rsa &&\
    git clone "${MY_REPO}" &&\
    rm -f /root/.ssh/id_rsa

Затем выполните сборку с помощью команды

docker build --tag=sshtest --build-arg SSH_KEY="$(cat ~/.ssh/path-to-private.key)" .

передача правильного пути к вашему закрытому SSH-ключу.

^ с Docker 1.9

@benton Вы можете внимательно посмотреть на вывод docker inspect sshtest и docker history sshtest . Я думаю, вы обнаружите, что метаданные в конечном изображении содержат ваш секрет, даже если они недоступны внутри самого контекста контейнера ...

@ljrittle Хорошее VAR . Думаю, здесь все еще требуется внешний обходной путь.

Возможно, одна из причин того, что собственное решение еще не разработано, заключается в том, что существует несколько обходных путей. Но я согласен с большинством других здесь, что встроенное решение будет лучше служить пользователям и соответствовать философии Docker «с включенными батареями».

Из документов ...

Примечание: не рекомендуется использовать переменные времени сборки для передачи секретов, таких как ключи github, учетные данные пользователя и т. Д.

(https://docs.docker.com/engine/reference/builder/#arg)

Я не думаю, что путь к файлу применим к этому, примечание о том, чтобы разрешить простой видимый пароль / токен в вашем журнале консоли.

Я не слежу за @jcrombez. Пример заключался в передаче ключа ssh как переменной через ARG . Итак, это применимо.

С точки зрения риска безопасности это совсем другое:

docker build --tag=sshtest --build-arg SSH_KEY="$(cat ~/.ssh/path-to-private.key)" .

чем это :

docker build --tag=sshtest --build-arg SSH_KEY="mykeyisthis" .

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

Полагаю, в командной строке.

Однако, как отметил @ljrittle и @benton признал, каким - либо образом использовать --build-arg / ARG будет совершено в сборке. Так что его осмотр откроет информацию о ключе. Оба оставляют состояние в последнем контейнере докеров и оба страдают одной и той же уязвимостью на этом конце. Следовательно, почему докер не рекомендует этого делать.

_ПОЛЬЗОВАТЕЛЬСКИЙ ОПРОС_

_Лучший способ получать уведомления об обновлениях - использовать кнопку _Подписаться_ на этой странице.

Пожалуйста, не используйте комментарии «+1» или «У меня тоже это есть» по поводу проблем. Мы автоматически
соберите эти комментарии, чтобы цепочка оставалась короткой.

Люди, перечисленные ниже, проголосовали за эту проблему, оставив +1 комментарий:

@ fletcher91
@benlemasurier
@dmuso
@probepark
@saada
@ianAndrewClark
@jakirkham
@galindro
@luisguilherme
@akurkin
@allardhoeve
@SevaUA
@sankethkatta
@kouk
@cliffxuan
@ kotlas92
@taion

_ПОЛЬЗОВАТЕЛЬСКИЙ ОПРОС_

_Лучший способ получать уведомления об обновлениях - использовать кнопку _Подписаться_ на этой странице.

Пожалуйста, не используйте комментарии «+1» или «У меня тоже это есть» по поводу проблем. Мы автоматически
соберите эти комментарии, чтобы цепочка оставалась короткой.

Люди, перечисленные ниже, проголосовали за эту проблему, оставив +1 комментарий:

@parknicker
@dursk
@adambiggs

С точки зрения риска безопасности это совсем другое:

docker build --tag=sshtest --build-arg SSH_KEY="$(cat ~/.ssh/path-to-private.key)" .

кроме вашей истории bash, они точно такие же; есть много мест, где эта информация может оказаться.

Например, предположим, что запросы API могут регистрироваться на сервере;

Вот журнал демона для docker build --tag=sshtest --build-arg SSH_KEY="fooobar" .

DEBU[0090] Calling POST /v1.22/build
DEBU[0090] POST /v1.22/build?buildargs=%7B%22SSH_KEY%22%3A%22fooobar%22%7D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&memory=0&memswap=0&rm=1&shmsize=0&t=sshtest&ulimits=null
DEBU[0090] [BUILDER] Cache miss: &{[/bin/sh -c #(nop) ARG SSH_KEY]}
DEBU[0090] container mounted via layerStore: /var/lib/docker/aufs/mnt/de3530a82a1a141d77c445959e4780a7e1f36ee65de3bf9e2994611513790b8c
DEBU[0090] container mounted via layerStore: /var/lib/docker/aufs/mnt/de3530a82a1a141d77c445959e4780a7e1f36ee65de3bf9e2994611513790b8c
DEBU[0090] Skipping excluded path: .wh..wh.aufs
DEBU[0090] Skipping excluded path: .wh..wh.orph
DEBU[0090] Applied tar sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef to 91f79150f57d6945351b21c9d5519809e2d1584fd6e29a75349b5f1fe257777e, size: 0
INFO[0090] Layer sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef cleaned up

_ПОЛЬЗОВАТЕЛЬСКИЙ ОПРОС_

_Лучший способ получать уведомления об обновлениях - использовать кнопку _Подписаться_ на этой странице.

Пожалуйста, не используйте комментарии «+1» или «У меня тоже это есть» по поводу проблем. Мы автоматически
соберите эти комментарии, чтобы цепочка оставалась короткой.

Люди, перечисленные ниже, проголосовали за эту проблему, оставив +1 комментарий:

@ cj2

Я пытаюсь поместить в контейнер простое приложение Ruby / Rack. Gemfile ссылается на несколько частных драгоценных камней. В тот момент, когда bundle install запускается и пытается получить доступ к частным репозиториям, я начинаю получать эту ошибку

Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Я смог обойти это, но не без раскрытия моего закрытого ключа. Так не пойдет. Пожалуйста, включите переадресацию аутентификации ssh.

+1 за пересылку ssh во время сборки. Из-за этого нельзя использовать go get с частными репозиториями; (

+1 для включения этого варианта использования безопасным способом

_ПОЛЬЗОВАТЕЛЬСКИЙ ОПРОС_

_Лучший способ получать уведомления об обновлениях - использовать кнопку _Подписаться_ на этой странице.

Пожалуйста, не используйте комментарии «+1» или «У меня тоже это есть» по поводу проблем. Мы автоматически
соберите эти комментарии, чтобы цепочка оставалась короткой.

Люди, перечисленные ниже, проголосовали за эту проблему, оставив +1 комментарий:

@lukad

Просто читая это очень интересное обсуждение, мне интересно, может ли простое решение решить эти проблемы. Я думаю, что в Dockerfile есть опция, позволяющая исключить / игнорировать определенные внутренние каталоги / файлы при создании снимков. Насколько это может быть сложно?

т.е.

ИСКЛЮЧИТЬ .ssh

Я думаю, что это применимо ко всем последующим шагам, поэтому, если вы поместите его после FROM, вы можете добавлять свои ключи столько, сколько хотите, и строить как обычно, и никогда не нужно беспокоиться о том, что ключи случайно окажутся в вашем образе (предоставлено вам может потребоваться добавить их на каждом этапе, когда они потребуются, но вам не придется беспокоиться о том, что они окажутся в изображении)

Предложение @benton работает нормально, и демон докера будет регистрировать ключ id_rsa только в том случае, если он находится в режиме отладки.

Еще более приятный способ раскрыть ключ во время сборки:

# Dockerfile
ARG SSH_KEY
RUN eval `ssh-agent -s` > /dev/null \
    && echo "$SSH_KEY" | ssh-add - \
    && git clone [email protected]:private/repository.git

docker build -t my_tag --build-arg SSH_KEY="$(< ~/.ssh/id_rsa)" .

Ха, хотя он действительно просто сидит, если вы посмотрите на docker inspect my_tag .. так что не уверен, каково реальное значение boot-arg, кроме того, что он немного аккуратнее, чем ENV.

И, если у вас есть пароль для ключа id_rsa, я думаю, вы могли бы быть плохим человеком и сделать:

# Dockerfile
ARG SSH_KEY
ARG SSH_PASS
RUN eval `ssh-agent -s` > /dev/null \
    && echo "echo $SSH_PASS" > /tmp/echo_ps && chmod 700 /tmp/echo_ps \
    && echo "$SSH_KEY" | SSH_ASKPASS=/tmp/echo_ps DISPLAY= ssh-add - \
    && git clone [email protected]:private/repository.git
    && rm /tmp/echo_ps

docker build -t my_tag --build-arg SSH_KEY="$(< ~/.ssh/id_rsa)" --build-arg SSH_PASS=<bad_idea> .

Конечно, трудно объяснить, что это даже отдаленно хорошая идея ... но я полагаю, что все мы люди.

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

Я бы сказал, просто поставьте ваши зависимости и ДОБАВЬТЕ весь проект ... но иногда что-то нужно делать сейчас.

@SvenDowideit @thaJeztah Есть ли решение этой проблемы? Я пытался следить за потоком, но между закрытием и открытием других потоков и множества мнений я понятия не имею, что команда Docker будет делать и когда.

Лучшее, но требует реализации?

Сборка Docker использует ssh-agent внутри сборки для прокси-сервера ssh вашего хоста, а затем использует ваши ключи, не зная их!

Для тех, кто только изучает проксирование ssh-agent: github спешит на помощь

Оригинальная идея @phemmer .

@yordis Я не думаю, что в этой ветке есть «отличное» решение, которое пока еще находится в свободном доступе.

Этот комментарий от docker / docker-py # 980, кажется, указывает на то, что если вы скопируете свои ключи ssh в каталог ключей корневого пользователя на вашей хост-системе, демон будет использовать эти ключи. Однако я безумный новичок в этом отношении, так что кто-то другой может уточнить.


Хорошо но не самое лучшее

Передача ключа с аргументами сборки docker 1.8.
Предостережения .

Определенно плохая идея

Многие люди также рекомендовали здесь временно добавить ключ в контекст сборки, а затем быстро удалить его. Звучит действительно опасно, потому что, если ключ закрадывается в одну из коммитов, любой, кто использует контейнер, может получить доступ к этому ключу, проверив конкретный коммит.


Почему это еще никуда не делось?

Требуется проектное предложение, эта проблема _cah_- _luttered_, и идеи на данный момент только расплывчаты. Фактические детали реализации теряются в тумане «что, если бы мы сделали x» и +1. Чтобы организовать работу и приступить к работе над этой столь необходимой функцией, те, у кого есть возможные решения, должны создать файл. . .

проектное предложение

а затем укажите эту проблему.

У меня есть новости по этому поводу.

На прошлой неделе на DockerCon нас побудили задавать самые сложные вопросы в павильоне Docker «Спросите экспертов», поэтому я подошел и коротко побеседовал с умным и дружелюбным инженером с обнадеживающим названием Solutions Architect. Я дал ему краткое изложение этой проблемы, которое, надеюсь, я передал точно, потому что он заверил меня, что это можно сделать с помощью _only_ docker-compose ! Детали того, что он предлагал, включали многоэтапную сборку - возможно, для накопления зависимостей в другом контексте, чем окончательная сборка приложения - и, похоже, предполагали использование объемов данных во время сборки.

К сожалению, у меня нет опыта работы с docker-compose, поэтому я не мог следить за всеми деталями, но он заверил меня, что если я напишу ему с точной проблемой, он ответит с решением. Итак, я написал то, что, надеюсь, является достаточно ясным письмом , в котором есть ссылка на эту открытую проблему GitHub. И сегодня утром я получил ответ от него, с его заверением, что он ответит, когда что-нибудь придумает.

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

@benton Я использую следующую конфигурацию docker-compose.yaml, чтобы делать вещи, описанные в этой теме:

version: '2'
services:
  serviceName:
     volumes:
      - "${SSH_AUTH_SOCK}:/tmp/ssh-agent"
    environment:
      SSH_AUTH_SOCK: /tmp/ssh-agent

Убедитесь, что ssh-agent запущен на хост-машине и знает ключ (вы можете проверить его с помощью команды ssh-add -L).

Обратите внимание, что вам может потребоваться добавить

Host *
  StrictHostKeyChecking no

в контейнер .ssh / config.

Привет @WoZ! спасибо за ответ, выглядит достаточно просто, так что я попробую :)

У меня есть вопрос, как вы можете использовать это с автоматическими сборками в Docker Hub? Насколько я понимаю, там нет возможности использовать композитный файл :(

@garcianavalon работает хорошо, но только для run , а не build . Еще не работает с Docker для Mac, хотя, по-видимому, он находится в списке задач.

Изменить: https://github.com/docker/for-mac/issues/410

Мы придумали еще 2 обходных пути для наших конкретных нужд:

1) Настройте собственное зеркало пакета для npm, pypi и т. Д. За нашим VPN, таким образом нам не нужен SSH.

2) На всех хост-машинах у нас уже есть доступ к частным репозиториям, поэтому мы клонируем / загружаем частный пакет локально на хост-машину, запускаем установку его пакета, чтобы загрузить его, затем с помощью -v сопоставить том с докером, затем создаем докер.

Сейчас мы используем вариант 2).

Что касается docker run , docker-ssh-agent-forward, кажется, предоставляет элегантное решение и работает в Docker для Mac / Linux.

По-прежнему может быть хорошей идеей КОПИРОВАТЬ файл known_hosts с хоста вместо его создания в контейнере (менее безопасный), поскольку ssh-agent, похоже, не пересылает известные хосты.

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

Один из способов обойти это ограничение - установить md5 / date для объявлений зависимостей сборки (например, package.json ), поместить результат в изображение и повторно использовать то же изображение, если файл не изменился. Использование хеша в имени изображения позволит кэшировать несколько состояний. Его также необходимо объединить с предустановленным дайджестом образа.

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

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

Мое конкретное решение не работало с 1.9.0 - оказалось, что функция, представленная в 1.8.0, на которую я полагался, не была преднамеренной, и поэтому она была удалена.

Хотя принцип моего решения остается в порядке (для этого просто требуется, чтобы у вас был DNS-сервер на вашем компьютере, который а) ваша машина использует и б) вы можете добавлять записи в соответствующие места), я не могу сказать, что с энтузиазмом рекомендую это больше.

Спасибо за дополнительную информацию @aidanhs!

Некоторые обновления, касающиеся предлагаемого мной решения: на самом деле хэши не нужно объединять, поскольку можно просто использовать хэш базового изображения сразу после добавления файла объявления зависимостей. Более того, лучше просто смонтировать файл known_host как том, поскольку ssh-agent в любом случае может использоваться только во время выполнения - и более безопасен, поскольку он содержит список всех хостов, к которым вы подключаетесь.

Я реализовал полное решение для node / npm, и его можно найти здесь с подробной документацией и примерами: https://github.com/iheartradio/docker-node

Конечно, эти принципы можно распространить и на другие фреймворки.

Та же проблема: как что-то построить, если для этого чего-то требуются учетные данные SSH для проверки и создания ряда проектов во время сборки внутри контейнера докеров без записи учетных данных в образ или базовый образ.

Мы работаем над этим, создавая двухэтапный процесс сборки. Создается "сборочный" образ, содержащий зависимости источника / ключей / сборки. После сборки он запускается для извлечения результатов сборки в tar-файл, который позже добавляется в образ «развертывания». Затем образ сборки удаляется, и все, что публикуется, - это образ «развертывания». Это имеет приятный побочный эффект, заключающийся в уменьшении размеров контейнера / слоя.

@ binarytemple-bet365 см. https://github.com/iheartradio/docker-node, чтобы увидеть сквозной пример, который делает именно это. Я использую более двух шагов, поскольку использую контейнер службы ssh, предварительную установку (базовый образ до установки частных зависимостей), установку (состояние контейнера после установки частных зависимостей во время выполнения) и пост-установку (добавляет команды, которые были у вас после установки частных зависимостей) для оптимизации скорости и разделения проблем.

Проверьте Rocker , это чистое решение.

@Sodki Я рокер - это чистое и продуманное решение. Жаль, что команда докеров просто не взяла этот проект под свое крыло и отказалась от поддержки docker build . Спасибо.

Все еще нет лучшего способа? :(

Кто-нибудь пробовал эту новую штуку для сквоша? https://github.com/docker/docker/pull/22641 Возможно, это собственное решение для докеров, которое мы ищем. Собираюсь попробовать сейчас и доложить, чтобы посмотреть, как это пойдет.

Спустя 2+ года это еще не исправлено 😞 Пожалуйста, команда Docker что-нибудь с этим поделайте

Похоже, у меня работает новая опция --squash в 1.13:
http://g.recordit.co/oSuMulfelK.gif

Я создаю его с помощью: docker build -t report-server --squash --build-arg SSH_KEY="$(cat ~/.ssh/github_private_key)" .

Поэтому, когда я делаю docker history или docker inspect , ключ не отображается.

Мой Dockerfile выглядит так:

FROM node:6.9.2-alpine

ARG SSH_KEY

RUN apk add --update git openssh-client && rm -rf /tmp/* /var/cache/apk/* &&\
  mkdir -p /root/.ssh && chmod 0700 /root/.ssh && \
  ssh-keyscan github.com > /root/.ssh/known_hosts

RUN echo "$SSH_KEY" > /root/.ssh/id_rsa &&\
  chmod 0600 /root/.ssh/id_rsa

COPY package.json .

RUN npm install
RUN rm -f /root/.ssh/id_rsa

# Bundle app source
COPY . .

EXPOSE 3000

CMD ["npm","start"]

@ kienpham2000 , ваш снимок экрана выглядит так, как будто он все еще содержит ключи - не могли бы вы проверить вывод docker history с флагом --no-trunc и сообщить здесь, отображаются ли закрытые ключи в докере история?

@ryanschwartz, вы правы, --no-trunc показывает всю эту чертову штуку, это не летает.

@ kienpham2000
Еще одна вещь, которую они представили в выпуске 1.13:

Секреты сборки
• включает секреты времени сборки с помощью флага —build-secret
• создает файлы tmpfs во время сборки и раскрывает секреты
построить контейнеры, которые будут использоваться во время сборки.
https://github.com/docker/docker/pull/28079

Может, это сработает?

Секреты сборки не вошли в 1.13, но, надеюсь, войдут в 1.14.

15 декабря 2016 г. в 9:45 "Alex" [email protected] написал:

@ kienpham2000 https://github.com/kienpham2000
Еще одна вещь, которую они представили в выпуске 1.13:

Секреты сборки
• включает секреты времени сборки с помощью флага —build-secret
• создает файлы tmpfs во время сборки и раскрывает секреты
построить контейнеры, которые будут использоваться во время сборки.
• # 28079 https://github.com/docker/docker/pull/28079

Может, это сработает?

-
Вы получаете это, потому что подписаны на эту беседу.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/docker/docker/issues/6396#issuecomment-267393020 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AAdcPDxrctBP2TlCtXen-Y_uY8Y8B09Sks5rIXy2gaJpZM4CD4SM
.

Итак, год спустя: Нет, это плохая идея. Вы НЕ ДОЛЖНЫ этого делать. Есть и другие решения. Например, Github может предоставлять токены доступа. Вы можете использовать их в файлах конфигурации / переменных среды с меньшим риском, поскольку вы можете указать, какие действия разрешены для каждого токена.

Решение - реализовать пересылку SSH. Как, например, Vagrant.

Может кто-нибудь объяснить мне, почему это так сложно реализовать?

@omarabid -

Что касается вашего предложения использовать токены доступа, они в конечном итоге будут храниться в слое, и их может быть так же опасно оставлять лежать там, как ключ SSH. Даже если бы у него был доступ только для чтения, большинство людей не хотели бы, чтобы другие имели доступ только для чтения к их репозиториям. Кроме того, может потребоваться частый отзыв / ротация / распространение; с этим немного легче справиться для каждого разработчика и т. д., чем с «основными» токенами доступа.

Решение для секретов сборки, упомянутое в нескольких комментариях, выглядит так, будто это шаг в правильном направлении, но лучше всего использовать SSH-агент. Возможно, можно было бы использовать агент SSH в сочетании с секретами сборки, я не уверен.

Для разработчиков / систем CI естественно использовать агент SSH во время операций git / build. Это намного безопаснее, чем наличие открытого текста, закрытого ключа без пароля, который необходимо отозвать / заменить в массовом порядке в различных системах. Кроме того, с агентами SSH нет возможности зафиксировать данные закрытого ключа в изображении. В худшем случае в образе останется переменная окружения / SSH_AUTH_SOCK.

Я получил этот последний обходной путь, не показывая содержимое секретного ключа или не используя дополнительный сторонний инструмент docker (надеюсь, секретное хранилище во время встроенного PR будет скоро объединено).

Я использую aws cli для загрузки общего закрытого ключа из S3 в текущее репозиторий хоста. Этот ключ зашифрован при хранении с помощью KMS. После загрузки ключа Dockerfile просто скопирует этот ключ во время процесса сборки и удалит его после, содержимое не отображается в docker inspect или docker history --no-trunc

Сначала загрузите закрытый ключ github с S3 на хост-машину:

# build.sh
s3_key="s3://my-company/shared-github-private-key"
aws configure set s3.signature_version s3v4
aws s3 cp $s3_key id_rsa --region us-west-2 && chmod 0600 id_rsa

docker build -t app_name .

Dockerfile выглядит так:

FROM node:6.9.2-alpine

ENV id_rsa /root/.ssh/id_rsa
ENV app_dir /usr/src/app

RUN mkdir -p $app_dir
RUN apk add --update git openssh-client && rm -rf /tmp/* /var/cache/apk/* && mkdir -p /root/.ssh && ssh-keyscan github.com > /root/.ssh/known_hosts

WORKDIR $app_dir

COPY package.json .
COPY id_rsa $id_rsa
RUN npm install && npm install -g gulp && rm -rf $id_rsa

COPY . $app_dir
RUN rm -rf $app_dir/id_rsa

CMD ["start"]

ENTRYPOINT ["npm"]

@ kienpham2000 , почему это решение не сохраняет ключ в слое изображения? Действия копирования и удаления ключа выполняются отдельными командами, поэтому существует слой, на котором должен быть ключ.
Наша команда до вчерашнего дня использовала ваше решение, но мы нашли улучшенное решение:

  • Мы генерируем предварительно подписанный URL-адрес для доступа к ключу с помощью aws s3 cli и ограничиваем доступ примерно на 5 минут, мы сохраняем этот предварительно подписанный URL-адрес в файл в каталоге репо, затем в dockerfile мы добавляем его к изображению.
  • В dockerfile у нас есть команда RUN, которая выполняет все эти шаги: используйте предварительный URL-адрес, чтобы получить ключ ssh, запустить npm install и удалить ключ ssh.
    Если выполнить это одной командой, ключ ssh не будет сохранен ни на каком уровне, но будет сохранен предварительно подписанный URL-адрес, и это не проблема, потому что URL-адрес станет недействительным через 5 минут.

Скрипт сборки выглядит так:

# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .

Dockerfile выглядит так:

FROM node

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    ssh -o StrictHostKeyChecking=no [email protected] || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]

@diegocsandrim спасибо, что указали на это, мне очень нравится ваше решение, я собираюсь обновить наши материалы здесь. Спасибо, что поделился!

Я немного новичок в этой теме, но, по сути, кажется, что люди пытаются решить проблему, которую лучше решить с помощью PKI. Не все обязательно пытаются сохранить ту же проблему, в которой PKI была бы лучшим решением, но достаточно ссылок, кажется, указывает на то, что это может быть то, что следует учитывать.

Это кажется раздражающим, но принципиально возможно

  • создать локальный центр сертификации
  • есть процесс для создания сертификата
  • иметь процесс выдачи сертификата
  • иметь процесс отзыва указанного сертификата
  • есть демоны ssh, использующие PKI

И если люди считают, что это возможно, тогда, пожалуйста, непременно создайте это и откройте исходный код, в конце концов, когда вся работа должна быть сделана хорошо. Я понятия не имею, безопасна ли сборка roumen petrov и не отмечена ли исходный код (не проверял tar), поэтому я понятия не имею, насколько она безопасна.

https://security.stackexchange.com/questions/30396/how-to-set-up-openssh-to-use-x509-pki-for-authentication

https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html

@mehmetcodes : наличие PKI на самом деле не решает проблему. Чтобы аутентификация SSH на основе PKI работала, вам все равно необходимо загрузить закрытый ключ в образ.

Если у вас нет местного центра сертификации, который выдает очень короткие сертификаты (например, менее часа), и вы не отзываете сертификат сразу после успешной сборки, это небезопасно.

Если вам удастся создать недолговечный процесс сертификата, это не сильно отличается от простого использования нового ключа SSH, который вы отзываете сразу после завершения сборки.

О, это раздражает еще больше, но я должен знать кое-что, или почему это могло существовать в дикой природе?

https://blog.cloudflare.com/red-october-cloudflares-open-source-implementation-of-the-two-man-rule/
https://blog.cloudflare.com/how-to-build-your-own-public-key-infrastructure/

Я не знаю, временный ключ SSH, вероятно, намного лучше для большинства случаев использования, но есть что-то тревожное в каждом обращении, включая тот, который я предложил, особенно в этом контексте.

Обычно вместо этого вы просто монтируете том с помощью ключа, но это не помогает в необходимости докера для решения Mac / moby.

кто, черт возьми, такой Моби?

@белый цвет
Image of Moby

У меня на MacOS вот что:

bash-3.2$ docker run -t -i -v "$SSH_AUTH_SOCK:/tmp/ssh_auth_sock" -e "SSH_AUTH_SOCK=/tmp/ssh_auth_sock" python:3.6 ssh-add -l
docker: Error response from daemon: Mounts denied:
The path /var/folders/yb/880w03m501z89p0bx7nsxt580000gn/T//ssh-DcwJrLqQ0Vu1/agent.10466
is not shared from OS X and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> File Sharing.
See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.
.

/ var / - это псевдоним, с которым Docker, похоже, борется. Но если я добавлю к пути $ SSH_AUTH_SOCK префикс /private (т.е. разрешенный путь псевдонима), тогда Docker сможет прочитать файл, но я получу:

bash-3.2$ docker run -t -i -v "/private$SSH_AUTH_SOCK:/tmp/ssh_auth_sock" -e "SSH_AUTH_SOCK=/tmp/ssh_auth_sock" python:3.6 ssh-add -l
Could not open a connection to your authentication agent.

В этот момент мне интересно, насколько плохо просто…

docker run -v ~/.ssh:/root/.ssh python:3.6 bash

?

docker build  --build-arg ssh_prv_key="$(cat ~/.ssh/id_rsa_no_pass)" --build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" --squash .

А затем внутри файла Docker:

ARG ssh_prv_key
ARG ssh_pub_key

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan github.com > /root/.ssh/known_hosts

# Add the keys and set permissions
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    echo "$ssh_pub_key" > /root/.ssh/id_rsa.pub && \
    chmod 600 /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa.pub

И не забудьте включить

RUN rm -f /root/.ssh/id_rsa /root/.ssh/id_rsa.pub

как последний шаг.

Уловка здесь в том, что ваш закрытый ключ не должен быть защищен паролем.

Проблема с предыдущим комментарием заключается в том, что ключи попадают в слои ... rm не удаляет из предыдущего слоя, поскольку каждая строка в файле докеров является одним слоем ..

Разве docker secret решает эту проблему?
WDYT @thaJeztah

секрет докера (пока) недоступен во время сборки и доступен только в службах (так что еще не для docker run )

При использовании многоэтапных сборок что-то вроде этого может сработать (набираю текст на моем телефоне, поэтому позвольте мне связать суть, которую я создал некоторое время назад); https://gist.github.com/thaJeztah/836c4220ec024cf6dd48ffa850f07770

Я больше не связан с Docker, но, как это возможно, что эта проблема существует так долго. Я не пытаюсь называть это, а вместо того, чтобы понять, какие усилия необходимы для исправления этого, потому что когда я имел дело с этим, это кажется действительно очень распространенной проблемой для любой компании, которая извлекает частные пакеты, такие как ruby gems из закрытое репо.

Заботится ли Moby об этой проблеме? Думаю, почему это должно быть так сложно для чего-то, что кажется не таким уж большим делом.

Прошло почти 3 года 😢

@yordis docker builder был заморожен на год или два. Команда Docker заявила, что конструктор достаточно хорош и что они сосредоточивают свои усилия на другом. Но этого больше нет, и с тех пор в конструкторе были внесены два изменения. Стадии для сквоша и мустли. Так что секреты времени сборки могут быть уже в пути.

Для перенаправления ssh-agent во время выполнения я бы рекомендовал https://github.com/uber-common/docker-ssh-agent-forward

Думаю, почему это должно быть так сложно для чего-то, что кажется не таким уж большим делом.

@yord читает верхнее описание этой проблемы, реализация этого далеко не тривиальная задача; Сказав это, если у кого-то есть предложение по техническому дизайну для этого, не стесняйтесь открывать вопрос или PR для обсуждения. Также обратите внимание, что для части _build_ был запущен проект buildkit для будущих улучшений построителя; https://github.com/moby/buildkit

@thaJeztah Я хотел бы иметь необходимые навыки, но у меня их нет.

@villlem , знаете ли вы какие-нибудь

Еженедельные отчеты для застройщика можно найти здесь; https://github.com/moby/moby/tree/master/reports/builder Секреты времени сборки по-прежнему указаны в последнем отчете, но можно использовать справку

Мы используем решение @diegocsandrim , но с промежуточным этапом шифрования, чтобы не оставлять незашифрованный ключ SSH в S3.

Этот дополнительный шаг означает, что ключ не может быть восстановлен из образа Docker (URL-адрес для его загрузки истекает через пять минут) и не может быть восстановлен из AWS (поскольку он зашифрован с помощью сменяющегося пароля, известного только образу докера) .

В build.sh:

BUCKET_NAME=my_bucket
KEY_FILE=my_unencrypted_key
openssl rand -base64 -out passfile 64
openssl enc -aes-256-cbc -salt -in $KEY_FILE -kfile passfile | aws s3 cp - s3://$BUCKET_NAME/$(hostname).enc_key
aws s3 presign s3://$BUCKET_NAME/$(hostname).enc_key --expires-in 300 > ./pre_sign_url
docker build -t my_service

И в Dockerfile:

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - | openssl enc -aes-256-cbc -d -kfile passfile > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    mkdir /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan github.com > /root/.ssh/known_hosts && \
    [commands that require SSH access to Github] && \
    rm ./my_key && \
    rm ./passfile && \
    rm -rf /root/.ssh/

если вы используете docker run вы должны смонтировать свой .ssh с помощью --mount type=bind,source="${HOME}/.ssh/",target="/root/.ssh/",readonly . Только чтение - это магия, он маскирует обычные разрешения, а ssh в основном видит разрешения 0600, которыми он доволен. Вы также можете поиграть с -u root:$(id -u $USER) чтобы пользователь root в контейнере записывал любые файлы, которые он создает, с той же группой, что и ваш пользователь, поэтому, надеюсь, вы можете по крайней мере прочитать их, если не полностью записать их без необходимости chmod / chown .

Ну наконец то.

Я считаю, что теперь эту проблему можно решить, используя всего docker build , используя многоступенчатые сборки .
Просто COPY или ADD ключ SSH или другой секрет, где бы он вам ни понадобился, и используйте его в операторах RUN , как хотите.

Затем используйте второй оператор FROM для запуска новой файловой системы и COPY --from=builder для импорта некоторого подмножества каталогов, не содержащих секрет .

(На самом деле я еще не пробовал это, но если функция работает, как описано ...)

Многоступенчатые сборки

Я проверил следующую технику:

  1. Передайте _расположение закрытого ключа_ в качестве аргумента сборки, например GITHUB_SSH_KEY , на первый этап многоступенчатой ​​сборки.
  2. Используйте ADD или COPY чтобы записать ключ туда, где он нужен для аутентификации. Обратите внимание, что если местоположение ключа является путем локальной файловой системы (а не URL-адресом), он не должен _не_ находиться в файле .dockerignore , иначе директива COPY не будет работать. Это имеет значение для окончательного изображения, как вы увидите на шаге 4 ...
  3. Используйте ключ по мере необходимости. В приведенном ниже примере ключ используется для аутентификации на GitHub. Это также работает для репозиториев Ruby bundler и частных репозиториев Gem. В зависимости от того, сколько кодовой базы вам нужно включить на этом этапе, вы можете снова добавить ключ в качестве побочного эффекта от использования COPY . или ADD . .
  4. ПРИ НЕОБХОДИМОСТИ ИЗВЛЕКИТЕ КЛЮЧ . Если местоположение ключа - это путь к локальной файловой системе (а не URL-адрес), то вполне вероятно, что он был добавлен вместе с кодовой базой, когда вы сделали ADD . или COPY . Это, вероятно, _точно каталог_, который будет скопирован в окончательный образ среды выполнения, поэтому вы, вероятно, также захотите включить оператор RUN rm -vf ${GITHUB_SSH_KEY} только вы закончите использовать ключ.
  5. Как только ваше приложение полностью встроено в его WORKDIR , начните второй этап сборки с нового оператора FROM , указывающего желаемый образ времени выполнения. Установите все необходимые зависимости времени выполнения, а затем COPY --from=builder вместо WORKDIR из первого этапа.

Вот пример Dockerfile , демонстрирующий описанную выше технику. Предоставление аргумента GITHUB_SSH_KEY Build проверит аутентификацию GitHub при сборке, но ключевые данные _не_ будут включены в окончательный образ времени выполнения. GITHUB_SSH_KEY может быть путем к файловой системе (в каталоге сборки Docker) или URL-адресом, который обслуживает данные ключа, но сам ключ не должен быть зашифрован в этом примере.

########################################################################
# BUILD STAGE 1 - Start with the same image that will be used at runtime
FROM ubuntu:latest as builder

# ssh is used to test GitHub access
RUN apt-get update && apt-get -y install ssh

# The GITHUB_SSH_KEY Build Argument must be a path or URL
# If it's a path, it MUST be in the docker build dir, and NOT in .dockerignore!
ARG GITHUB_SSH_KEY=/path/to/.ssh/key

  # Set up root user SSH access for GitHub
ADD ${GITHUB_SSH_KEY} /root/.ssh/id_rsa

# Add the full application codebase dir, minus the .dockerignore contents...
# WARNING! - if the GITHUB_SSH_KEY is a file and not a URL, it will be added!
COPY . /app
WORKDIR /app

# Build app dependencies that require SSH access here (bundle install, etc.)
# Test SSH access (this returns false even when successful, but prints results)
RUN ssh -o StrictHostKeyChecking=no -vT [email protected] 2>&1 | grep -i auth

# Finally, remove the $GITHUB_SSH_KEY if it was a file, so it's not in /app!
# It can also be removed from /root/.ssh/id_rsa, but you're probably not going
# to COPY that directory into the runtime image.
RUN rm -vf ${GITHUB_SSH_KEY} /root/.ssh/id*

########################################################################
# BUILD STAGE 2 - copy the compiled app dir into a fresh runtime image
FROM ubuntu:latest as runtime
COPY --from=builder /app /app

_Может_ быть безопаснее передавать сами ключевые данные в аргументе сборки GITHUB_SSH_KEY , а не в _location_ ключевых данных. Это предотвратит случайное включение ключевых данных, если они хранятся в локальном файле и затем добавляются с помощью COPY . . Однако для этого потребуется использовать echo и перенаправление оболочки для записи данных в файловую систему, что может не работать во всех базовых образах. Используйте тот метод, который наиболее безопасен и подходит для вашего набора базовых изображений.

@jbiel Еще год, и решение, которое я нашел, - использовать что-то вроде Vault.

Вот ссылка с двумя методами (сквош и промежуточный контейнер, описанный ранее @benton)

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

Решение.
Создайте сценарий bash (~ / bin / docker-compose или аналогичный):

#!/bin/bash

trap 'kill $(jobs -p)' EXIT
socat TCP-LISTEN:56789,reuseaddr,fork UNIX-CLIENT:${SSH_AUTH_SOCK} &

/usr/bin/docker-compose $@

И в Dockerfile с помощью socat:

...
ENV SSH_AUTH_SOCK /tmp/auth.sock
...
  && apk add --no-cache socat openssh \
  && /bin/sh -c "socat -v UNIX-LISTEN:${SSH_AUTH_SOCK},unlink-early,mode=777,fork TCP:172.22.1.11:56789 &> /dev/null &" \
  && bundle install \
...
or any other ssh commands will works

Затем запустите docker-compose build

@benton, почему вы используете RUN rm -vf ${GITHUB_SSH_KEY} /root/.ssh/id* ? Разве это не должно быть просто RUN rm -vf /root/.ssh/id* ? Или, может быть, я неправильно понял смысл здесь.

@benton А еще делать небезопасно:

RUN ssh -o StrictHostKeyChecking=no -vT [email protected] 2>&1

Вы должны проверить отпечаток пальца

Я решил эту проблему таким способом

ARGS USERNAME
ARGS PASSWORD
RUN git config --global url."https://${USERNAME}:${PASSWORD}@github.com".insteadOf "ssh://[email protected]"

затем строить с

docker build --build-arg USERNAME=use --build-arg PASSWORD=pwd. -t service

Но сначала ваш частный сервер git должен поддерживать репозиторий username:password clone.

Команда @zeayes RUN хранится в истории контейнера. Так что ваш пароль будет виден другим.

Правильный; при использовании --build-arg / ARG эти значения будут отображаться в истории сборки. _Возможно использовать этот метод, если вы используете многоэтапные сборки _и_ доверяете хосту, на котором создаются образы (т. Е. Ни один недоверенный пользователь не имеет доступа к локальной истории сборки), _и_ промежуточные этапы сборки не помещаются в реестр.

Например, в следующем примере USERNAME и PASSWORD будут присутствовать в истории только для первого этапа («строитель»), но не будут в истории для последнего этапа;

FROM something AS builder
ARG USERNAME
ARG PASSWORD
RUN something that uses $USERNAME and $PASSWORD

FROM something AS finalstage
COPY --from= builder /the/build-artefacts /usr/bin/something

Если только окончательное изображение (созданное "finalstage") помещено в реестр, то USERNAME и PASSWORD не будут в этом образе.

_Однако_ в истории локального кэша сборки эти переменные все еще будут там (и сохранены на диске в виде обычного текста).

Построитель следующего поколения (использующий

@kinnalru @thaJeztah thx, я использую многоступенчатые сборки, но пароль можно увидеть в истории контейнера кеша, спасибо!

@zeayes Ой! Я вижу, что сделал ошибку при копировании / вставке; последний этап не должен использовать FROM builder .. . Вот полный пример; https://gist.github.com/thaJeztah/af1c1e3da76d7ad6ce2abab891506e50

Этот комментарий @kinnalru - правильный способ сделать это https://github.com/moby/moby/issues/6396#issuecomment -348103398

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

Мне потребовалось время, чтобы понять это, так что вот более четкое и улучшенное объяснение. Я изменил код @kinnalru на --network=host и localhost , поэтому вам не нужно знать свой IP-адрес. ( суть здесь )

Это docker_with_host_ssh.sh , он обертывает докер и перенаправляет SSH_AUTH_SOCK в порт на localhost:

#!/usr/bin/env bash

# ensure the processes get killed when we're done
trap 'kill $(jobs -p)' EXIT

# create a connection from port 56789 to the unix socket SSH_AUTH_SOCK (which is used by ssh-agent)
socat TCP-LISTEN:56789,reuseaddr,fork UNIX-CLIENT:${SSH_AUTH_SOCK} &
# Run docker
# Pass it all the command line args ($@)
# set the network to "host" so docker can talk to localhost
docker $@ --network='host'

В Dockerfile мы подключаемся через localhost к хостам ssh-agent:

FROM python:3-stretch

COPY . /app
WORKDIR /app

RUN mkdir -p /tmp

# install socat and ssh to talk to the host ssh-agent
RUN  apt-get update && apt-get install git socat openssh-client \
  # create variable called SSH_AUTH_SOCK, ssh will use this automatically
  && export SSH_AUTH_SOCK=/tmp/auth.sock \
  # make SSH_AUTH_SOCK useful by connecting it to hosts ssh-agent over localhost:56789
  && /bin/sh -c "socat UNIX-LISTEN:${SSH_AUTH_SOCK},unlink-early,mode=777,fork TCP:localhost:56789 &" \
  # stuff I needed my ssh keys for
  && mkdir -p ~/.ssh \
  && ssh-keyscan gitlab.com > ~/.ssh/known_hosts \
  && pip install -r requirements.txt

Затем вы можете создать свое изображение, вызвав скрипт:

$ docker_with_host_ssh.sh build -f ../docker/Dockerfile .

@cowlicks вас может заинтересовать этот docker build --ssh для пересылки агента SSH во время сборки; https://github.com/docker/cli/pull/1419. Синтаксис Dockerfile все еще не включен в официальные спецификации, но вы можете использовать директиву syntax=.. в своем Dockerfile, чтобы использовать интерфейс, который его поддерживает (см. Пример / инструкции в запросе на перенос).

Этот запрос на перенос будет частью предстоящего выпуска 18.09.

Похоже, это теперь доступно в версии 18.09. Поскольку эта ветка появляется перед примечаниями к выпуску и средней публикацией, я буду размещать здесь кросс-посты.

Примечания к выпуску:
https://docs.docker.com/develop/develop-images/build_enhancements/#using -ssh-to-access-private-data-in-builds

Средний пост:
https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

Очень волнующе.

Я думаю, мы можем закрыть это, потому что у нас есть docker build --ssh сейчас

Связанная проблема с компоновкой здесь: docker / compose # 6865. Функциональные возможности для использования Составьте и предоставьте сокет агента SSH контейнерам, которые, как было отмечено, приземляются в следующем выпуске-кандидате 1.25.0-rc3 ( выпуски ).

Была ли эта страница полезной?
0 / 5 - 0 рейтинги