Использование ключей 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


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.


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

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

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в конечном изображении.


Старый пост, но я хочу подчеркнуть, что на сегодняшний день это лучший способ сделать это до 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команды, которая позволяет вводить файлы во время работы контейнера.


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 непосредственно для своей работы: для этого они и были разработаны.


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 вне контейнера.


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


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 - имя команды контейнера изображения

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


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/


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)"

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


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" ]

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

Этот 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 для установки ключей, поскольку итерации вашего контейнера могут оставить закрытые ключи позади.


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.