Использование ключей SSH внутри контейнера Docker

324

У меня есть приложение, которое выполняет различные забавные вещи с помощью Git (например, запуск git clone & git push), и я пытаюсь сделать это в docker-ize.

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

Я попытался скопировать его /root/.ssh/, изменив$HOME , создать оболочку git ssh, но все равно не повезло.

Вот Dockerfile для справки:

#DOCKER-VERSION 0.3.4                                                           

from  ubuntu:12.04                                                              

RUN  apt-get update                                                             
RUN  apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN  add-apt-repository ppa:chris-lea/node.js                                   
RUN  echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN  apt-get update                                                             
RUN  apt-get install nodejs -y                                                  

ADD . /src                                                                       
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa                             
RUN   cd /src; npm install                                                      

EXPOSE  808:808                                                                 

CMD   [ "node", "/src/app.js"]

app.js запускает команды git как git pull

ebensing
источник
3
Любой, кто подходит к этому вопросу, должен подумать об окончании игры, так как легко создать дыру в безопасности и забыть об этом здесь, если вы не будете осторожны. Прочитайте все ответы и выберите мудро.
Джош Хабдас

Ответы:

144

Это более сложная проблема, если вам нужно использовать SSH во время сборки. Например, если вы используете git clone, или в моем случае pipиnpm для загрузки из частного хранилища.

Решение, которое я нашел, состоит в том, чтобы добавить ваши ключи, используя --build-argфлаг. Затем вы можете использовать новую экспериментальную --squashкоманду (добавлена ​​1.13), чтобы объединить слои, чтобы ключи больше не были доступны после удаления. Вот мое решение:

Команда построения

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

Dockerfile

FROM python:3.6-slim

ARG ssh_prv_key
ARG ssh_pub_key

RUN apt-get update && \
    apt-get install -y \
        git \
        openssh-server \
        libmysqlclient-dev

# 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

# Avoid cache purge by adding requirements first
ADD ./requirements.txt /app/requirements.txt

WORKDIR /app/

RUN pip install -r requirements.txt

# Remove SSH keys
RUN rm -rf /root/.ssh/

# Add the rest of the files
ADD . .

CMD python manage.py runserver

Обновление: если вы используете Docker 1.13 и у вас есть экспериментальные функции, вы можете добавить --squashкоманду build, которая объединит слои, удаляя ключи SSH и скрывая их от docker history.

Дэниел ван Флаймен
источник
13
Этот поток вопросов GitHub будет указывать, что этот подход все еще не является безопасным. Смотрите этот комментарий для другого аналогичного решения.
eczajk
4
Другое решение вместо сдавливания - добавить и удалить ключ в той же команде RUN, а между добавлением и удалением вы используете его для того, для чего он вам нужен.
Бенджамин Хаммер Норгаард
2
Может быть, вы можете удалить строки для создания id_rsa.pubфайла, так как это не требуется.
LCB
1
Вместо сквоша используйте многоэтапные сборки изображений .
Ричард Кифер
Если ваш ключ защищен паролем, используйте $(openssl rsa -in ~/.ssh/id_rsa)вместо этого
BroiSatse
89

Оказывается, при использовании Ubuntu ssh_config не верен. Вам нужно добавить

RUN  echo "    IdentityFile ~/.ssh/id_rsa" >> /etc/ssh/ssh_config

в ваш Dockerfile, чтобы он распознал ваш ключ ssh.

ebensing
источник
2
Вы, вероятно, также должны установить правильное имя пользователя, как этоRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
monofone
1
Зачем кому-то копировать закрытый ключ с хост-машины в контейнер? Команда в порядке, но я не вижу смысла в выполнении вышеупомянутого ...
Владимир Джуричич
12
Это не безопасно! Смотрите мое решение ниже для последней версии 1.13 Docker. @ebensing
Даниэль ван Флаймен
1
@VladimirDjuricic Есть и такие вещи, как ключи развертывания.
Зельфир Кальцталь
на самом деле вам нужно запустить ssh-keygen -A для правильной настройки ssh в минимальном контейнере ubuntu. Затем вы можете добавить ключи pub / priv и запустить sshd. У меня есть запись в моем файле Docker: «RUN ssh-keygen -A» в качестве одного из шагов.
piotrektt
84

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

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

В моем случае это нормально, вот что я использую:

# Setup for ssh onto github
RUN mkdir -p /root/.ssh
ADD id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN echo "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config
yellowcap
источник
91
Это будет держать ваш ключ в изображении, не делайте этого.
CppLearner
12
@CppLearner вы правы, здесь хранится ключ в изображении, и в некоторых случаях это может быть проблемой безопасности. Спасибо за выделение этого. Тем не менее, есть много ситуаций, когда это идеально сэкономить. Например, для изображений, которые хранятся в частном репозитории, или изображений, которые построены непосредственно на рабочем сервере, копируя локальные ключи в образ.
желтая шапка
2
Кроме того, если вы устанавливаете своих поставщиков в Dockerfile, ничто не помешает вам удалить ключ ssh после установки поставщиков.
SebScoFr
2
@SebScoFr, очевидно, ключи будут храниться на одном из слоев, даже если вы удалите их в более поздней команде (см. Ссылку в обновленном ответе). Таким образом, изображение всегда будет отображать ключ ssh, и решение следует использовать только для личных изображений!
yellowcap
1
@yellowcap нет, если вы
помните
57

Если вы используете docker compose , простой способ - перенаправить SSH-агент следующим образом:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent
Aistis
источник
23
Просто обратите внимание, что это не работает для хостов Mac, независимо от того, используете ли вы docker-машину (через VirtualBox) или Docker для Mac (которая использует xhyve), потому что доменные сокеты unix не проксируются.
Джо Шоу
SSH_AUTH_SOCKпеременная, которая содержит путь к ssh-агенту
Aistis
2
более подробная информация о SSH_AUTH_SOCK blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add
JuanPablo
1
ssh-forwarding теперь также поддерживается на хостах macOS - вместо монтирования пути $SSH_AUTH_SOCKвы должны монтировать этот путь - /run/host-services/ssh-auth.sock.
Якуб Кукул
48

Расширяя ответ Питера Грейнджера, я смог использовать многоступенчатую сборку, доступную с Docker 17.05. Официальная страница гласит:

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

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

# Stage 1: get sources from npm and git over ssh
FROM node:carbon AS sources
ARG SSH_KEY
ARG SSH_KEY_PASSPHRASE
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan bitbucket.org > /root/.ssh/known_hosts && \
    echo "${SSH_KEY}" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa
WORKDIR /app/
COPY package*.json yarn.lock /app/
RUN eval `ssh-agent -s` && \
    printf "${SSH_KEY_PASSPHRASE}\n" | ssh-add $HOME/.ssh/id_rsa && \
    yarn --pure-lockfile --mutex file --network-concurrency 1 && \
    rm -rf /root/.ssh/

# Stage 2: build minified production code
FROM node:carbon AS production
WORKDIR /app/
COPY --from=sources /app/ /app/
COPY . /app/
RUN yarn build:prod

# Stage 3: include only built production files and host them with Node Express server
FROM node:carbon
WORKDIR /app/
RUN yarn add express
COPY --from=production /app/dist/ /app/dist/
COPY server.js /app/
EXPOSE 33330
CMD ["node", "server.js"]

.dockerignoreповторяет содержимое .gitignoreфайла (предотвращает копирование node_modulesи последующие distкаталоги проекта):

.idea
dist
node_modules
*.log

Пример команды для построения изображения:

$ docker build -t ezze/geoport:0.6.0 \
  --build-arg SSH_KEY="$(cat ~/.ssh/id_rsa)" \
  --build-arg SSH_KEY_PASSPHRASE="my_super_secret" \
  ./

Если ваш закрытый ключ SSH не имеет парольной фразы, просто укажите пустой SSH_KEY_PASSPHRASE аргумент.

Вот как это работает:

1). Только на первом этапеpackage.json , yarn.lockфайлы и секретный ключ SSH копируются первым промежуточным изображением имени sources. Чтобы избежать дальнейших запросов парольной фразы ключа SSH, она автоматически добавляется в ssh-agent. в заключениеyarn команда устанавливает все необходимые зависимости от NPM и клонирует частные репозитории git из Bitbucket через SSH.

2). Второй этап создает и минимизирует исходный код веб-приложения и помещает его в distкаталог следующего промежуточного изображения с именем production. Обратите внимание, что исходный код установленnode_modules скопирован из образа с именем, sourcesсозданным на первом этапе этой строкой:

COPY --from=sources /app/ /app/

Возможно, это также может быть следующая строка:

COPY --from=sources /app/node_modules/ /app/node_modules/

У нас есть только node_modules каталог из первого промежуточного изображения здесь, нет SSH_KEYиSSH_KEY_PASSPHRASE аргументов больше. Все остальное, необходимое для сборки, скопировано из каталога нашего проекта.

3). На третьем этапе мы уменьшаем размер конечного изображения, которое будет помечено как ezze/geoport:0.6.0включающее толькоdist каталог из второго промежуточного изображения с именем productionи устанавливая Node Express для запуска веб-сервера.

Список изображений дает вывод, как это:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ezze/geoport        0.6.0               8e8809c4e996        3 hours ago         717MB
<none>              <none>              1f6518644324        3 hours ago         1.1GB
<none>              <none>              fa00f1182917        4 hours ago         1.63GB
node                carbon              b87c2ad8344d        4 weeks ago         676MB

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

Если вы бежите

$ docker history ezze/geoport:0.6.0 --no-trunc

Вы не увидите никаких упоминаний SSH_KEYи SSH_KEY_PASSPHRASEв конечном изображении.

Ezze
источник
Старый пост, но я хочу подчеркнуть, что на сегодняшний день это лучший способ сделать это до 18.09. Сквош не нужен и подвержен риску. С многоступенчатым, вы знаете, что вносите только те артефакты, которые хотите. Думайте о сквоше как об отказе от файлов, которые вам не нужны, а о многоступенчатом - как о подписке Этот ответ должен быть выше. Запекание ваших ключей ssh ​​на изображении - ужасная практика.
mritalian
@ezze Большое спасибо за этот очень полезный пост :) SSH-агент сводит меня с ума, я сделал нечто похожее на то, что вы сделали: я правильно вижу в журналах сборки докера, Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)но когда я проверяю в другом RUN или даже в том же RUN Команда, выполнив a, ssh-add -lговорит мне, что «Агент не имеет идентичности». Начинаете стягивать с меня волосы, есть мысли?
Алекс
40

Чтобы ввести ваш ключ ssh, в контейнере у вас есть несколько решений:

  1. Используя Dockerfile с ADDинструкцией, вы можете добавить его во время процесса сборки

  2. Просто делать что-то вроде cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. Использование docker cpкоманды, которая позволяет вводить файлы во время работы контейнера.

creack
источник
2
Итак, на данный момент я пытался скопировать его в /root/.ssh/id_rsa, но по-прежнему получаю сообщение «Ошибка проверки ключа хоста. Fatal: Remote end неожиданно зависает» из Git, что, я уверен, означает, что это не использует ключ по любой причине. Так что я думаю, что мне нужно сделать что-то еще, чтобы заставить систему использовать ее как ключ ssh? Не уверен, как именно отладить этот. (и я знаю, что этот ключ работает, потому что он запускается без проблем с хоста)
ebensing
Вы можете убедиться, что / etc / ssh / ssh_config настроен на правильный файл ключа?
Creack
1
Есть ли хороший способ проверить файлы контейнера докера? Или я должен просто попытаться скопировать в правильной конфигурации?
ebensing
3
Я только что попробовал с «базовым» образом, выполнил apt-get install openssh-serverи поместил свой ключ в /root/.ssh/id_rsa, и он работал нормально. Какое изображение вы используете?
Creack
если вам нужно проверить файл контейнера, лучшим способом будет зафиксировать и запустить получившееся изображение с помощью 'cat'.
13
15

Одним из кроссплатформенных решений является использование привязки для совместного использования .sshпапки хоста с контейнером:

docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>

Подобно переадресации агента, этот подход сделает открытые ключи доступными для контейнера. Дополнительным преимуществом является то, что он работает и с пользователем без полномочий root и подключит вас к GitHub. Однако следует учесть, что все содержимое (включая закрытые ключи) из .sshпапки будет общим, поэтому этот подход желателен только для разработки и только для доверенных образов контейнера.

Мохаммед Азим
источник
1
это может сработать, но не во время docker buildтолько во времяdocker run
Александр Миллс
3
В том-то и дело. Вы не хотите помещать ваши ключи ssh в файл Docker.
Мохаммед Азим
2
Учитывая, что переадресация агента SSH не работает за пределами Linux, это прекрасное решение для бесперебойной работы в среде разработки.
Джош Хабдас
Я использую Docker docker-compose upв моей локальной Windows 10. Как мне использовать ваше решение в этом сценарии?
llaaalu
По сути, вы спрашиваете, как отобразить объем в Docker Compose. Выше есть ответ, отвечающий на это. В частности, для Windows это может помочь stackoverflow.com/questions/41334021/…
Мохаммад Азим
14

Контейнеры Docker следует рассматривать как собственные «сервисы». Чтобы разделить проблемы, вы должны разделить функции:

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

2) Используйте контейнер для запуска задачи клонирования git (т. Е. Это только клонирование задания), связывая контейнер данных с ним при запуске.

3) То же самое для ssh-ключа: поместите это том (как предложено выше) и свяжите его со службой git clone, когда вам это нужно

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

Теперь, если само ваше приложение представляет собой интерфейс git, вы можете рассмотреть возможность использования API-интерфейсов REST github или bitbucket непосредственно для своей работы: для этого они и были разработаны.

MRE
источник
13

Эта строка является проблемой:

ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa

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

ADD id_rsa /root/.ssh/id_rsa

И поместите файл id_rsa в тот же каталог, где находится ваш Dockerfile.

Проверьте это для более подробной информации: http://docs.docker.io/reference/builder/#add

Дэн Кедер
источник
4
Это также проблема безопасности, потому что она помещает закрытый ключ в изображение, которое можно легко забыть.
Майк Д
docker cpпросто кладет его в контейнер, а не изображение, верно?
Александр Миллс
13

У нас была похожая проблема при установке npm во время сборки Docker.

Вдохновленный решением от Daniel van Flymen и объединив его с git url rewrite , мы нашли немного более простой способ аутентификации установки npm из частных репозиториев github - мы использовали токены oauth2 вместо ключей.

В нашем случае зависимости npm были указаны как "git + https://github.com/ ..."

Для аутентификации в контейнере необходимо переписать URL-адреса, чтобы они подходили для аутентификации ssh (ssh: //git@github.com/) или для аутентификации токена (https: // $ {GITHUB_TOKEN} @ github.com /)

Команда построения:

docker build -t sometag --build-arg GITHUB_TOKEN=$GITHUB_TOKEN . 

К сожалению, я нахожусь на докере 1.9, поэтому опции --squash еще нет, в конце концов ее нужно добавить

Dockerfile:

FROM node:5.10.0

ARG GITHUB_TOKEN

#Install dependencies
COPY package.json ./

# add rewrite rule to authenticate github user
RUN git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"

RUN npm install

# remove the secret token from the git config file, remember to use --squash option for docker build, when it becomes available in docker 1.13
RUN git config --global --unset url."https://${GITHUB_TOKEN}@github.com/".insteadOf

# Expose the ports that the app uses
EXPOSE 8000

#Copy server and client code
COPY server /server 
COPY clients /clients
Маркко Паас
источник
11

Перешлите сокет аутентификации ssh в контейнер:

docker run --rm -ti \
        -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock \
        -e SSH_AUTH_SOCK=/tmp/ssh_auth.sock \
        -w /src \
        my_image

Ваш сценарий сможет выполнить git clone .

Дополнительно: если вы хотите, чтобы клонированные файлы принадлежали определенному пользователю, вам нужно использовать, chownтак как использование другого пользователя, кроме root, внутри контейнера сделаетgit сбою.

Вы можете сделать эту публикацию в среде контейнера некоторых дополнительных переменных:

docker run ...
        -e OWNER_USER=$(id -u) \
        -e OWNER_GROUP=$(id -g) \
        ...

После клонирования вы должны выполнить chown $OWNER_USER:$OWNER_GROUP -R <source_folder>установку правильного владельца, прежде чем покинуть контейнер, чтобы файлы были доступны пользователю без полномочий root вне контейнера.

edupo
источник
1
В более новых версиях Docker вы можете передать, -u root:$(id -u $USER)по крайней мере, файлы, принадлежащие той же основной группе, что и ваш пользователь, что должно сделать их все по крайней мере читабельными, sudoесли только кто-то не создает их с 0600разрешениями.
dragon788
@ dragon788 Я думаю, у вас есть опечатка: -u root:$(id -u $USER)должно быть -g.
edupo
Хороший звонок! Я не могу исправить это с мобильного, скоро попробую на рабочем столе.
dragon788
У меня /tmp/ssh_auth.sock: No such file or directoryсейчас он /tmp/ssh-vid8Zzi8UILE/agent.46016на моей принимающей машине
vladkras
@vladkras ошибка довольно общая. Может быть вызвано из-за разрешений /tmpвнутри вашего контейнера. Или опечатка в команде запуска Docker. Убедитесь, что оператор связывания правильный -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock: порядок важен, точка с запятой также важна. Пожалуйста, проверьте докер документацию для получения дополнительной помощи.
edupo
10

Как уже прокомментировал eczajk в ответе Даниеля ван Флаймена, извлекать ключи и использовать --squashих небезопасно , так как они все еще будут видны в истории ( docker history --no-trunc).

Вместо этого с Docker 18.09 вы можете теперь использовать функцию «строить секреты». В моем случае я клонировал частное git-репо, используя мой SSH-ключ hosts, со следующим в моем Dockerfile:

# syntax=docker/dockerfile:experimental

[...]

RUN --mount=type=ssh git clone [...]

[...]

Чтобы использовать это, вам нужно включить новый бэкэнд BuildKit перед запуском docker build:

export DOCKER_BUILDKIT=1

И вам нужно добавить --ssh defaultпараметр в docker build.

Больше информации об этом здесь: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

FRSC
источник
1
Лучшее решение ИМХО. Мне пришлось сделать еще две вещи, чтобы заставить его работать: 1) добавить свой закрытый ключ в ssh-agent с помощью ssh-add ~/.ssh/id_rsaи 2) добавить хост git в known_hosts, то есть для bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Мориц Ринглер
Я не смог заставить это работать вообще. Я по-прежнему получаю ошибки разрешений: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.несмотря на передачу --ssh defaultфлага в моей сборке Docker и использование --mount=type=sshкоманды run, где я git clone. Я могу клонировать тот же репо без проблем на сборочной машине. Он просто не работает в контейнере сборки Docker. Я подозреваю, что Mac-версия Docker фактически не передает ssh-клиент.
PMende
@PMende, если бы вы смогли выяснить эту проблему, которую вы упомянули, потому что я тоже сталкиваюсь с тем же.
Садан А.
@SadanArshad Оказывается, эта функция в настоящее время поддерживается, только если вы запускаете Docker с компьютера с Linux. Он не работает, если вы запускаете команды Docker с Mac (и, возможно, также с Windows, хотя я не могу подтвердить).
PMende
Жаль, что не работает с docker-compose ... github.com/docker/compose/issues/6440
Алексис Уилк
9

Эта проблема действительно раздражает. Поскольку вы не можете добавить / скопировать какой-либо файл вне контекста dockerfile, это означает, что невозможно просто связать ~ / .ssh / id_rsa в /root/.ssh/id_rsa изображения, и когда вам определенно нужен ключ для выполнения каких-либо sshed как git clone из приватной ссылки репо ... во время создания вашего образа докера.

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

  1. в вашем докер-файле:

    • добавить этот файл как /root/.ssh/id_rsa
    • делай что хочешь, например git clone, composer ...
    • rm /root/.ssh/id_rsa в конце
  2. скрипт, который нужно сделать за один раз:

    • cp ваш ключ к папке, содержащей файл dockerfile
    • сборка докера
    • рм скопированный ключ
  3. каждый раз, когда вам нужно запустить контейнер из этого образа с некоторыми требованиями ssh, просто добавьте -v для команды run, например:

    docker запустите -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa - имя команды контейнера изображения

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

ImLeo
источник
1
«Поскольку вы не можете добавлять / копировать файлы вне контекста dockerfile», вы видели docker cp? Он используется для «Копирования файлов / папок между контейнером и вашим хостом».
Джонатон Рейнхарт
@JonathonReinhart, спасибо за указание на это. Да, docker cpмог бы добиться цели. Однако в этой самой ситуации мне понадобился ключ ssh_key во время создания образа, и в то время контейнера не было ... обновит мое неясное выражение, в любом случае, спасибо.
ImLeo
9

Я столкнулся с той же проблемой сегодня и немного модифицированной версии с предыдущими постами, я нашел этот подход более полезным для меня

docker run -it -v ~/.ssh/id_rsa:/root/.my-key:ro image /bin/bash

(Обратите внимание, что флаг readonly, поэтому контейнер ни в коем случае не испортит мой ключ ssh.)

Внутри контейнера теперь я могу запустить:

ssh-agent bash -c "ssh-add ~/.my-key; git clone <gitrepourl> <target>"

Так что я не понимаю ту Bad owner or permissions on /root/.ssh/..ошибку, которая была замечена @kross

Тохо
источник
Спасибо! Это был ключ , чтобы он работал для меня: имея SSH-агент и SSH-надстройку в одной команде , как: ssh-agent bash -c "ssh-add...". Затем я могу передать это прямо в Docker Run. Все предыдущие примеры, которые я нашел, использовались eval ssh-agent, затем следовал ssh-add, и я не мог найти способ передать это evalчерез команду docker run.
Райанман
7

«Вы можете выборочно разрешить удаленным серверам обращаться к вашему локальному ssh-агенту, как если бы он работал на сервере»

https://developer.github.com/guides/using-ssh-agent-forwarding/

arreche
источник
4
docker run -i -t -v $ (ссылка для чтения -f $ SSH_AUTH_SOCK): / ssh-agent -e SSH_AUTH_SOCK = / ssh-agent ubuntu / bin / bash
Павел Хлобил
1
FruitL00P создал контейнер
Docker-Tunnel
6

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

$ sudo docker run -it -v /root/.ssh:/root/.ssh someimage bash

Помните, что docker запускается с помощью sudo (если вы этого не делаете), в этом случае вы будете использовать корневые ssh-ключи.

Луис Элизондо
источник
Использование этого метода работает с докером 0.11, но если вы используете рис, он выдаст паническую ошибку. Я не знаю почему
Луис Элизондо
3
Это был бы предпочтительный метод, трюк состоял бы в том, чтобы использовать ключи моего непривилегированного хост-пользователя в качестве корня контейнера. Как вы упоминаете, попытка сделать это не так, как пользователь root Bad owner or permissions on /root/.ssh/config.
кросс
это можно использовать только во время docker run, но не во время docker build.
ccpizza
3
@ccpizza, я рассматриваю это как преимущество. Многие из этих ответов оставляют закрытые ключи сохраненными в изображении; ключ остается сохраненным даже после удаления ключа в последующей команде слоя. Вводя закрытые ключи только во время выполнения (не в процессе сборки), они могут существовать только в контейнере (не в образе).
cowlinator
6

Начиная с docker API 1.39+(проверьте версию API с помощью docker version) сборки docker, вы можете --sshвыбрать опцию с сокетом агента или ключами, чтобы Docker Engine мог перенаправлять соединения агента SSH.

Команда сборки

export DOCKER_BUILDKIT=1
docker build --ssh default=~/.ssh/id_rsa .

Dockerfile

# syntax=docker/dockerfile:experimental
FROM python:3.7

# Install ssh client (if required)
RUN apt-get update -qq
RUN apt-get install openssh-client -y

# Download public key for github.com
RUN --mount=type=ssh mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts

# Clone private repository
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject

Больше информации:

Эдисон Аранго
источник
1
Расширение тильды у меня не сработало; Я получил: could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory. Используйте полный путь, если он не работает.
Slhck
3

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

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

Мы генерируем предварительный 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 git@github.com || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]
Сэм Х.
источник
1
Проблема этого решения заключается в том, что поскольку pre_sign_url будет меняться каждый раз, установка npm не может быть кэширована, даже если в файле packages.json нет изменений. Лучше взять ключ в build.sh и установить его в качестве аргумента сборки, чтобы он не менялся каждый раз
Йорк Ян
3

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

См. Ответ на мой вопрос stackoverflow для получения дополнительной информации

Питер Грейнджер
источник
3

Краткий обзор проблем SSH внутри контейнеров Docker подробно описан здесь . Для подключения к доверенным удаленным устройствам из контейнера без утечки секретов существует несколько способов:

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

Для использования ключа SSH в автономном контейнере Docker см. Методы, указанные выше, и рассмотрите недостатки каждого из них в зависимости от ваших конкретных потребностей. Однако, если вы работаете внутри Compose и хотите поделиться ключом к приложению во время выполнения (отражая практические возможности OP), попробуйте это:

  • Создайте docker-compose.envфайл и добавьте его в свой .gitignoreфайл.
  • Обновите свой docker-compose.ymlи добавьте env_fileдля службы, требующей ключ.
  • Доступ к открытому ключу из среды во время выполнения приложения, например, process.node.DEPLOYER_RSA_PUBKEYв случае приложения Node.js.

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

Дополнительные ресурсы:

Джош Хабдас
источник
3

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

Стадия 1 построение образа с помощью ssh

FROM ubuntu as sshImage
LABEL stage=sshImage
ARG SSH_PRIVATE_KEY
WORKDIR /root/temp

RUN apt-get update && \
    apt-get install -y git npm 

RUN mkdir /root/.ssh/ &&\
    echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa &&\
    chmod 600 /root/.ssh/id_rsa &&\
    touch /root/.ssh/known_hosts &&\
    ssh-keyscan github.com >> /root/.ssh/known_hosts

COPY package*.json ./

RUN npm install

RUN cp -R node_modules prod_node_modules

Этап 2: построить свой контейнер

FROM node:10-alpine

RUN mkdir -p /usr/app

WORKDIR /usr/app

COPY ./ ./

COPY --from=sshImage /root/temp/prod_node_modules ./node_modules

EXPOSE 3006

CMD ["npm", "run", "dev"] 

добавьте атрибут env в ваш файл compose:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

затем передайте аргументы из сценария сборки следующим образом:

docker-compose build --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)"

И удалите промежуточный контейнер для безопасности. Это поможет вам ура.

Devesh
источник
2

Простой и безопасный способ добиться этого без сохранения ключа в слое изображения Docker или прохождения гимнастики ssh_agent:

  1. В качестве одного из шагов в вашем Dockerfile, создайте .sshкаталог, добавив:

    RUN mkdir -p /root/.ssh

  2. Ниже указано, что вы хотите смонтировать каталог ssh как том:

    VOLUME [ "/root/.ssh" ]

  3. Убедитесь, что ваш контейнер ssh_configзнает, где найти открытые ключи, добавив следующую строку:

    RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config

  4. Предоставьте .sshкаталог локального пользователя контейнеру во время выполнения:

    docker run -v ~/.ssh:/root/.ssh -it image_name

    Или в вашем dockerCompose.ymlдобавить это под ключ громкости службы:

    - "~/.ssh:/root/.ssh"

Ваш финал Dockerfileдолжен содержать что-то вроде:

FROM node:6.9.1

RUN mkdir -p /root/.ssh
RUN  echo "    IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config

VOLUME [ "/root/.ssh" ]

EXPOSE 3000

CMD [ "launch" ]
Buchanora
источник
1

Я пытаюсь решить проблему другим способом: добавить открытый ключ ssh к изображению. Но в своих испытаниях я обнаружил, что "docker cp" предназначен для копирования из контейнера на хост. Пункт 3 в ответе скрипит, кажется, говорит, что вы можете использовать docker cp для внедрения файлов в контейнер. См. Https://docs.docker.com/engine/reference/commandline/cp/.

выдержка

Скопируйте файлы / папки из файловой системы контейнера в путь к хосту. Пути указаны относительно корня файловой системы.

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH
EricGreg
источник
Этот URL сейчас не работает.
Slm
Это устарело или неверно. Он может копировать в любом направлении, начиная с версии 1.8.2.
Джонатон Рейнхарт
1

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

FROM ubuntu:16.04
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
EXPOSE 22
RUN cp /root/auth/id_rsa.pub /root/.ssh/authorized_keys
RUN rm -f /root/auth
RUN chmod 700 /root/.ssh
RUN chmod 400 /root/.ssh/authorized_keys
RUN chown root. /root/.ssh/authorized_keys
CMD /usr/sbin/sshd -D

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

-d -v /home/thatsme/dockerfiles/auth:/root/auth -–publish=127.0.0.1:7001:22

Возможно, вы захотите взглянуть на https://github.com/jpetazzo/nsenter, который является еще одним способом открыть оболочку в контейнере и выполнить команды внутри контейнера.

Эндрю Пэйт
источник
1

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

docker run -v ~/.ssh:/mnt -it my_image /bin/bash -c "ln -s /mnt /root/.ssh; ssh user@10.20.30.40"

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

Jepper
источник
0

Вы можете использовать секреты для управления любыми конфиденциальными данными, которые нужны контейнеру во время выполнения, но вы не хотите хранить их в изображении или в управлении исходным кодом, например:

  • Имена пользователей и пароли
  • TLS сертификаты и ключи
  • SSH ключи
  • Другие важные данные, такие как имя базы данных или внутреннего сервера
  • Общие строки или двоичное содержимое (размером до 500 КБ)

https://docs.docker.com/engine/swarm/secrets/

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

Трэвис Бритз
источник
0

В моем случае у меня была проблема с nodejs и 'npm i' из удаленного репозитория. Я исправил добавление пользователя 'node' в контейнер nodejs и 700 в ~ / .ssh в контейнер.

Dockerfile:

USER node #added the part
COPY run.sh /usr/local/bin/
CMD ["run.sh"]

run.sh:

#!/bin/bash
chmod 700 -R ~/.ssh/; #added the part

докер-compose.yml:

nodejs:
      build: ./nodejs/10/
      container_name: nodejs
      restart: always
      ports:
        - "3000:3000"
      volumes:
        - ../www/:/var/www/html/:delegated
        - ./ssh:/home/node/.ssh #added the part
      links:
        - mailhog
      networks:
        - work-network

после этого начались работы

Дмитрий Урбанович
источник
-1

Проще всего получить учетную запись панели запуска и использовать: ssh-import-id

Сэм Шафран
источник
8
Вопрос был о закрытых ключах. ssh-import-idпохоже, он импортирует только открытые ключи.
cddr
-1

В работающем контейнере Docker вы можете запустить ssh-keygen с опцией docker -i (интерактивный). Это переадресует запросы контейнера для создания ключа внутри контейнера докера.

Джером Энтони
источник
1
И что потом? После этого вы ничего не можете сделать, потому что у вас нет на это разрешения.
Джонатон Рейнхарт
-1

Для debian / root / authorized_keys:

RUN set -x && apt-get install -y openssh-server

RUN mkdir /var/run/sshd
RUN mkdir -p /root/.ssh
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN  echo "ssh-rsa AAAA....yP3w== rsa-key-project01" >> /root/.ssh/authorized_keys
RUN chmod -R go= /root/.ssh
StanislavKo
источник