Використання SSH ключів всередині контейнера докера


324

У мене є додаток, який виконує різні цікаві речі з Git (наприклад, запуск клона git & git push), і я намагаюся його докер-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 .

Докерфайл

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команду збірки, яка об'єднає шари, видаляючи ключі 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
Це не безпечно! Дивіться моє рішення нижче щодо останньої версії Docker 1.13. @ebensing
Daniel van Flymen

1
@VladimirDjuricic Є такі речі, як ключі розгортання.
Зельфір Кальтшталь

насправді вам потрібно запустити ssh-keygen -A, щоб правильно встановити ssh на мінімальному контейнері ubuntu. Потім ви можете додати ключі pub / priv та запустити sshd. Я маю цей запис у своєму dockerfile: '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 Ви праві, це зберігає ключ на зображенні, і це може бути проблемою безпеки в деяких випадках. Дякуємо, що наголосили на цьому. Однак є багато ситуацій, коли це ідеально економить. Наприклад, для зображень, які зберігаються у приватному сховищі, або зображень, створених безпосередньо на виробничому сервері, що копіює локальні ключі до зображення.
yellowcap

2
Крім того, якщо ви встановите своїх постачальників в Dockerfile, нічого не заважає вам зняти ключ ssh після встановлення постачальників.
SebScoFr

2
@SebScoFr, мабуть, ключі будуть збережені в одному з шарів, навіть якщо ви видалите їх у наступній команді (див. Посилання в оновленій відповіді). Таким чином, зображення завжди виставлятиме ключ ssh, а рішення слід використовувати лише для приватних зображень!
yellowcap

1
@yellowcap не, якщо ви - розбийте збірку
Anoyz

56

Якщо ви використовуєте docker, складіть простий вибір - переслати 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 хостів, будь то докер-машина (через 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-переадресація тепер також підтримується на хостах macOS - замість того, щоб монтувати шлях $SSH_AUTH_SOCK, ви повинні змонтувати цей шлях - /run/host-services/ssh-auth.sock.
Якуб Кукул

47

Розгортаючи відповідь Пітера Грінгера, я зміг використовувати багатоетапну збірку, доступну з Докера 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 на зображенні - жахлива практика.
міріталіан

@ezze Дуже дякую за цей дуже корисний пост :) SSH-агент зводить мене з розуму, я зробив щось подібне, як те, що ти робив: я правильно бачу в журналах збирання докерів, Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)але коли я перевіряю в іншому RUN або навіть у тому ж RUN команда, виконуючи 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, але все одно отримую "Перевірка ключа хоста не вдалася. Фатально: Віддалений кінець зненацька завис" помилки від Git, що я впевнений, що це означає не використовує ключ з будь-якої причини. Тому я думаю, що є щось інше, що мені потрібно зробити, щоб насправді сказати системі використовувати її як ключ ssh? Не точно знаєте, як налагодити цей. (і я знаю, що цей ключ працює, тому що він працює без запитання від хоста)
ebensing

чи можете ви переконатися, що / etc / ssh / ssh_config орієнтується на правильний файл ключа?
скрип

1
Чи є хороший спосіб перевірити файли контейнера докер? Або я просто повинен спробувати скопіювати у правильній конфігурації?
ebensing

3
Я просто спробував із базовим зображенням, зробивши apt-get install openssh-serverі ввівши свій ключ у /root/.ssh/id_rsa, і це спрацювало чудово. Яке зображення ви використовуєте?
скрип

якщо вам потрібно перевірити файл контейнера, найкращим способом було б зафіксувати та запустити отримане зображення за допомогою "cat".
скрип

15

Одним з крос-платформних рішень є використання прив'язки для обміну .sshпапкою хоста на контейнер:

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

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


1
це може спрацювати, але не docker buildлише під часdocker run
Олександр Міллз

3
Саме в цьому і полягає. Ви не хочете вставляти свої ssh ключі у файл докера.
Мохаммед Азім

2
Враховуючи, що переадресація агента SSH не працює за межами Linux, це робить прекрасне рішення для запуску та роботи в середовищі розробки без великої суєти.
Джош Хабдас

Я запускаю докер, використовуючи docker-compose upв моїй локальній Windows 10. Як я повинен використовувати ваше рішення в цьому сценарії?
llaaalu

По суті, ви запитуєте, як відобразити об'єм у докерному складі. Вище є відповідь, що відповідає на це. Спеціально для Windows це може допомогти stackoverflow.com/questions/41334021/…
Мохаммед Азім

14

Докер-контейнери слід розглядати як "власні" послуги. Щоб розділити питання, слід розділити свої функції:

1) Дані повинні бути в контейнері даних: використовуйте пов'язаний об'єм для клонування репо в. Цей контейнер даних потім може бути пов'язаний із послугою, яка потребує цього.

2) Використовуйте контейнер, щоб виконати завдання по клонуванню git (тобто це лише клонування), пов'язуючи контейнер даних із ним під час запуску.

3) Те ж саме для ssh-ключа: покладіть його на об'єм (як запропоновано вище) та прив'яжіть його до служби клонування git, коли вам це потрібно

Таким чином, і завдання клонування, і ключ є ефемерними та активними лише в разі потреби.

Тепер, якщо ваш додаток сам по собі є інтерфейсом git, ви, можливо, захочете розглянути API github або bitbucket REST безпосередньо для вашої роботи: саме для цього вони були розроблені.


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

Натхненний рішенням від Натхневшись Даніелем ван Фліменом та поєднавши його з переписанням URL-адреси git , ми знайшли дещо простіший метод автентифікації встановлення 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 . 

На жаль, я перебуваю на docker 1.9, тому - варіанту сквош ще немає, з часом його потрібно додати

Докерфайл:

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 run. Переконайтеся, що твердження bind правильне -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock: Порядок важливий, а крапка з комою також важлива. Щоб отримати додаткову допомогу, перегляньте документацію докера .
edupo

10

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

Замість Docker 18.09 тепер ви можете використовувати функцію "будувати секрети". У моєму випадку я клонував приватне git repo, використовуючи SSH-ключ мого хоста із наступним в моєму 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-агента з ssh-add ~/.ssh/id_rsaта 2) додати git-хост до знаних_хостів, тобто для бітбукета: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прапора в моїй докерній збірці та використання --mount=type=sshв команді run, де я git clone. Я можу клонувати те саме репо без проблем на машині складання. Він просто виходить з ладу в контейнері збірки докерів. Я підозрюю, що mac-версія Docker насправді не передає ssh-клієнта.
PMende

@PMende, чи змогли ви розібратися з цим питанням, про яке ви згадали, бо я теж зіткнувся з тим же.
Садан А.

@SadanArshad Виявляється, ця функціональність наразі підтримується лише у тому випадку, якщо ви працюєте з Docker з машини Linux. Це не працює, якщо ви виконуєте команди Docker з Mac (і, мабуть, Windows, також, хоча я не можу підтвердити).
PMende

Шкода, що не працює з docker-compose ... github.com/docker/compose/isissue/6440
Алексіс Вілке

9

Це питання насправді дратує. Оскільки ви не можете додати / скопіювати жоден файл поза контекстом dockerfile, це означає, що неможливо просто зв’язати ~ / .ssh / id_rsa в /root/.ssh/id_rsa зображення, і коли вам точно потрібен ключ, щоб зробити якусь дію. як клон git із приватного посилання репо ... під час створення вашого зображення докера.

У будь-якому разі я знайшов рішення для вирішення, не настільки переконливого, але все-таки працював для мене.

  1. у вашому док-файлі:

    • додайте цей файл як /root/.ssh/id_rsa
    • робити те, що ти хочеш, наприклад, git clone, композитор ...
    • rm /root/.ssh/id_rsa в кінці
  2. сценарій, який потрібно зробити одним знімком:

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

    docker run -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

(Зверніть увагу, що прапор лише для читання, щоб контейнер ні в якому разі не зіпсував мій ключ 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...". Потім я можу передати це право на пробіг докера. Усі попередні приклади, які я знайшов використаними 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 $ (readlink -f $ SSH_AUTH_SOCK): / ssh-agent -e SSH_AUTH_SOCK = / ssh-agent ubuntu / bin / bash
Павло Хлобіл

1
frul00p створив контейнер докер-тунель таким чином: github.com/kingsquare/docker-tunnel
Мартін

6

Ви також можете зв’язати свій .ssh каталог між хостом і контейнером, я не знаю, чи має цей спосіб ніякі наслідки для безпеки, але це може бути найпростіший метод. Щось подібне повинно працювати:

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

Пам'ятайте, що докер працює з sudo (якщо ви цього не зробите), якщо це так, ви будете використовувати кореневі клавіші ssh.


Використання цього методу працює з docker 0,11, але якщо ви використовуєте фіг, це призведе до панічної помилки. Я не знаю чому
Луїс Елізондо

3
Це був би кращий метод, фокусом було б використання моїх непривілейованих ключів користувача хосту як кореня контейнера. Як ви вже згадували, намагатися зробити це не так, як дає користувач root-хост Bad owner or permissions on /root/.ssh/config.
крос

це можна використовувати лише під час docker run, але не під час docker build.
ccpizza

3
@ccpizza, я вважаю це перевагою. Багато з цих відповідей залишають приватні ключі, збережені у зображенні; ключ залишається збереженим навіть після вилучення ключа в наступній команді шару. Вводячи приватні ключі лише під час запуску (не збірки), вони можуть існувати лише в контейнері (не на зображенні).
ковбасник

6

Починаючи з docker API 1.39+(Перевірте версію API з docker version) збірка докера дозволяє--ssh надати або розетку агента, або клавіші, щоб Docker Engine передавав з'єднання агентів SSH.

Збірка команд

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

Докерфайл

# 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-адресу перед підписом у файл у каталозі repo, потім у 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 не може бути кешоване, навіть не змінивши файл пакети.json. Краще дістати ключ у build.sh і встановити його як аргумент збірки, щоб він не змінювався щоразу
Йорк Ян

3

У пізніших версіях докера (17.05) ви можете використовувати багатоетапні збірки . Що є найбезпечнішим варіантом, оскільки попередні збірки можуть бути використані лише при наступній збірці, а потім знищуються

Щоб отримати докладнішу інформацію, див . Відповідь на моє запитання


3

Короткий огляд проблем SSH всередині Docker-контейнерів детально описаний тут . Для підключення до надійних віддалених пристроїв зсередини контейнера без протікання секретів існує кілька способів:

Крім цього, також існує можливість використання магазину ключів, який працює в окремому контейнері докера, доступному під час виконання під час використання Compose. Недолік тут - додаткова складність завдяки машині, необхідній для створення та керування сховищем ключів, таким як Vault від HashiCorp .

Для використання ключа SSH в автономному контейнері Docker див. Вищезазначені методи та врахуйте недоліки кожного, залежно від ваших конкретних потреб. Якщо ви працюєте всередині Compose і хочете поділитися ключем до програми під час виконання (відображаючи практичні можливості ОП), спробуйте:

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

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

Додаткові ресурси:


3

Ви можете використовувати багатоетапну збірку для створення контейнерів. Це такий підхід, який ви можете використовувати: -

Перший етап створення зображення з 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 у свій композиційний файл:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

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

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

І вийміть проміжний контейнер для безпеки. Це допоможе вам ура.


2

Простий і безпечний спосіб досягти цього без збереження ключа в шарі зображення Докера або проходження гімнастики 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

Ви можете передати авторизовані ключі до свого контейнера за допомогою спільної папки та встановити дозволи, використовуючи такий файл докера:

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 на хості (утримуючи autorized_keys) з контейнером, а потім відкрити ssh-порт, який буде доступний через порт 7001 на хості.

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

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


1

Пізно до учасника, правда, як щодо цього, що дозволить ключам вашої операційної системи надати доступ до коріння всередині контейнера:

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

Докерфайл:

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

docker-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 / Author_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.