Клоніруйте приватне git repo з dockerfile


240

Я скопіював цей код з того, що, здається, є різними робочими докерфілами навколо, ось моє:

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# Update aptitude with new repo
RUN apt-get update

# Install software 
RUN apt-get install -y git python-virtualenv

# Make ssh dir
RUN mkdir /root/.ssh/

# Copy over private key, and set permissions
ADD id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN chown -R root:root /root/.ssh

# Create known_hosts
RUN touch /root/.ssh/known_hosts

# Remove host checking
RUN echo "Host bitbucket.org\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf

Це дає мені помилку

Step 10 : RUN git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf
 ---> Running in 0d244d812a54
Cloning into '/home/docker-conf'...
Warning: Permanently added 'bitbucket.org,131.103.20.167' (RSA) to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
2014/04/30 16:07:28 The command [/bin/sh -c git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf] returned a non-zero code: 128

Я вперше використовую dockerfiles, але з того, що я прочитав (і взяв із працюючих конфігурацій), я не можу зрозуміти, чому це не працює.

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

Редагувати:

У свій dockerfile я можу додати:

RUN cat /root/.ssh/id_rsa

І він виводить правильний ключ, тому я знаю, що він правильно скопійований.

Я також намагався зробити так, як радив Ной, і біг:

RUN echo "Host bitbucket.org\n\tIdentityFile /root/.ssh/id_rsa\n\tStrictHostKeyChecking no" >> /etc/ssh/ssh_config

Це, на жаль, також не працює.

Відповіді:


300

Мій ключ захищений паролем, що спричинило проблему. Нижче перелічено робочий файл (для допомоги майбутнім googlers)

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# Update aptitude with new repo
RUN apt-get update

# Install software 
RUN apt-get install -y git
# Make ssh dir
RUN mkdir /root/.ssh/

# Copy over private key, and set permissions
# Warning! Anyone who gets their hands on this image will be able
# to retrieve this private key file from the corresponding image layer
ADD id_rsa /root/.ssh/id_rsa

# Create known_hosts
RUN touch /root/.ssh/known_hosts
# Add bitbuckets key
RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

11
На всякий випадок, ось це посилання, що описує, як зняти захист паролем ключа
Томас

82
Просто FYI, після запуску RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts, зображення збереже це як шар. Якщо хтось захопить ваше зображення, він може отримати ключ ... навіть якщо ви видалите цей файл у більш пізньому шарі, b / c, він може повернутися до кроку 7, коли ви додали його.
Bernie Perez

23
Дякуємо за корисну відповідь. Але для нас збірка не вдалася випадковим чином, і після розслідування ми помітили, що ssh-keyscanза замовчуванням встановлено 5 секунд, який бітбукет часто перевищує. ssh-keyscanнавіть не повідомить про помилку. Тож краще бігайте, RUN ssh-keyscan -T 60 bitbucket.org >> /root/.ssh/known_hostsщоб бути в безпеці.
флюїдсон

5
Може хтось пояснить, чому біг ssh-keyscan- це проблема? Я розумію, що він просто потягне відкритий ключ Github / Bitbucket. Яку альтернативу можна використовувати, щоб вона не закінчилася шаром?
Педро

9
@Pedro Зокрема, крок із клавішами - це зовсім не проблема, ви абсолютно праві. Якщо що-небудь, ці хост-відкриті ключі слід максимально поширити. Детальну інформацію про known_hostsфайл див. У sshd (8) . Люди просто підтримують випадкові речі, коли вони звучать досить тривожно.
tne

99

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

  1. Створіть ключі ssh, за допомогою ssh-keygen -q -t rsa -N '' -f repo-keyяких ви отримаєте файли repo-key та repo-key.pub.

  2. Додайте repo-key.pub до ключів розгортання сховища.
    У GitHub перейдіть до [вашого сховища] -> Налаштування -> Клавіші розгортання

  3. Додайте щось подібне до свого Dockerfile:

    ДОБАВИТИ репо-ключ /
    РУН \
      chmod 600 / клавіша повторного замовлення && \  
      echo "IdentityFile / repo-key" >> / etc / ssh / ssh_config && \  
      echo -e "StrictHostKeyChecking ні" >> / etc / ssh / ssh_config && \  
      // ваші команди git clone тут ...
    

Зауважте, що вище вимикається StrictHostKeyChecking, тому вам не потрібні .ssh / known_hosts. Хоча мені, мабуть, більше подобається рішення з ssh-keyscan в одній з відповідей вище.


6
Попередження: у моїй конфігурації відлуння -e "..." також записується -e всередині файла. Просто зніміть прапор, і він прекрасно працює.
Конхілікультор

Ваша відповідь була абсолютно ідеальною, допомагаючи мені вирішити свою проблему. Дякую!
Девід Пойнтер

У мене все одно те саме питання: fatal: Could not read from remote repository.
Олексій

1
Дякую мільйонам! Я на краю проголошую любов до вас. Ви вирішили питання, з яким я боровся цілими днями!
Олександра

Відповідь, обрана на це питання, вже не є гарною відповіддю. Це було правильним у 2014 році, але на 2020 рік це правильна відповідь.
Bikal Basnet

70

Немає необхідності спіткнутися з конфігураціями ssh. Використовуйте файл конфігурації (не Dockerfile), який містить змінні середовища, і сценарій оболонки оновить ваш файл докера під час виконання. Ви зберігаєте жетони поза Dockerfiles і можете клонувати по https (не потрібно генерувати або передавати ключі ssh).

Перейдіть у Налаштування> Токени особистого доступу

  • Створіть персональний маркер доступу з repoувімкненим діапазоном.
  • Клон так: git clone https://MY_TOKEN@github.com/user-or-org/repo

Деякі коментатори зазначили, що якщо ви використовуєте спільний Dockerfile, це може відкрити ваш ключ доступу до інших людей у ​​вашому проекті. Хоча це може бути проблемою для вашого конкретного випадку використання, ось декілька способів вирішити це:

  • Скористайтеся скриптом оболонки, щоб прийняти аргументи, які можуть містити ваш ключ як змінну. Замініть змінну у вашому Dockerfile на sedподібну або подібну, тобто виклик сценарію, sh rundocker.sh MYTOKEN=fooякий замінить на https://{{MY_TOKEN}}@github.com/user-or-org/repo. Зауважте, що ви можете також використовувати файл конфігурації (у .yml або будь-якому форматі, який ви хочете), щоб зробити те саме, але зі змінними середовища.
  • Створіть користувача github (і генеруйте маркер доступу) лише для цього проекту

Про який контекст ви говорите Settings > Applications?
турболаден

1
Мінус цього підходу полягає в тому, що ви зберігаєте облікові дані для приватного репо в межах Dockerfile на відміну від підходу @ crooksey, який дозволить вам посилатися на ключ, який зберігається окремо від Dockerfile. Без контексту навколо того, як ОП зберігає Dockerfile, ми не можемо визначити, чи це спричинить проблему, але з особистого досвіду я люблю зберігати свої Dockerfiles у VCS і не хотів би вносити нічого, що містило облікові дані. Як тільки Докер реалізує здатність передавати env змінні для складання команди, тоді я згоден, це було б найчистішим рішенням.
Джаббслад

2
@CalvinFroedge на місцевому рівні Я припускаю, що ви маєте на увазі свого господаря? Мені невідомий спосіб викрити змінні середовища на хості контейнеру під час збирання, тому ми маємо відкриті проблеми, такі як цей github.com/docker/docker/isissue/6822 . Будь ласка, можете уточнити?
Jabbslad

1
Навіть більш чистий (розділення проблем): зв'язаний об'єм для клонованого репо + виділений контейнер лише для завдання по клонуванню + зв'язаний том лише за допомогою ключів SSH (або маркера, як ви запропонували). Див. Stackoverflow.com/a/30992047 , можливо поєднується зі stackoverflow.com/a/29981990 .
Петерино

9
Також питання стосується BITBUCKET repo, а не github repo.
Майкл Дрейпер

25

Іншим варіантом є використання багатоетапної збірки докерів для того, щоб ваші SSH ключі не були включені до остаточного зображення.

Як описано в моєму дописі, ви можете підготувати своє проміжне зображення з необхідними залежностями, щоб git клонувати, а потім COPYнеобхідні файли в остаточне зображення.

Крім того, якщо ми LABELпроміжні шари, ми навіть можемо видалити їх з машини, коли закінчимо.

# Choose and name our temporary image.
FROM alpine as intermediate
# Add metadata identifying these images as our build containers (this will be useful later!)
LABEL stage=intermediate

# Take an SSH key as a build argument.
ARG SSH_KEY

# Install dependencies required to git clone.
RUN apk update && \
    apk add --update git && \
    apk add --update openssh

# 1. Create the SSH directory.
# 2. Populate the private key file.
# 3. Set the required permissions.
# 4. Add github to our list of known hosts for ssh.
RUN mkdir -p /root/.ssh/ && \
    echo "$SSH_KEY" > /root/.ssh/id_rsa && \
    chmod -R 600 /root/.ssh/ && \
    ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

# Clone a repository (my website in this case)
RUN git clone git@github.com:janakerman/janakerman.git

# Choose the base image for our final image
FROM alpine

# Copy across the files from our `intermediate` container
RUN mkdir files
COPY --from=intermediate /janakerman/README.md /files/README.md

Тоді ми можемо будувати:

MY_KEY=$(cat ~/.ssh/id_rsa)
docker build --build-arg SSH_KEY="$MY_KEY" --tag clone-example .

Доведіть, що наші SSH-ключі вже немає:

docker run -ti --rm clone-example cat /root/.ssh/id_rsa

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

docker rmi -f $(docker images -q --filter label=stage=intermediate)

ARG SSH_PRIVATE_KEY потрібно замінити на ARG SSH_KEY
Джозеф Персі

не можемо ми просто видалити ключі, як тільки буде зроблений git clone?
Бронча

1
Ви можете це зробити, але вам потрібно зробити це як частина єдиного, RUNщоб не залишати ключ у попередньому шарі зображення. Від докера 1.13ви можете використовувати --squash експериментальний аргумент, який також видалить ключ SSH у ваших кінцевих шарах зображення.
Джейкер

19

Для сховища біткоїтів створіть пароль програми (настройки Bitbucket -> керування доступом -> пароль додатка, див. Зображення) з доступом для читання до репо і проекту.

меню користувача bitbucket

Тоді команда, яку ви повинні використовувати:

git clone https://username:generated_password@bitbucket.org/reponame/projectname.git

1
Найпростіший :) Я мушу визнати, що я віддаю перевагу підходу, заснованому на SSH, але я не міг отримати жодного з перерахованих вище ... файлів не знайдено тощо.
Janos

Я не бачу "Управління доступом" ... Я думаю, він застарів?
Мартін Тома

1
Працювали! Простий і простий ... Чудово!
Йоземі

2
Звичайно ... Вам просто потрібно натиснути на зображення профілю на лівій панелі, потім на налаштуваннях Bitbucket, і ви побачите щось подібне: imgur.com/EI33zj3
Josemy

1
Це працювало для мене. Однак у мене є підмодулі і --recursiveне працювали. Мені довелося вводити git cloneкожен підмодуль, що добре, але було б чудово, якби це працювало рекурсивно.
Заїлін Тамайо

14

Ви часто не хочете виконувати git clone приватне репо зсередини докерної збірки. Здійснення клону там передбачає розміщення приватних облікових даних ssh всередині зображення, де їх згодом може бути вилучено будь-ким, хто має доступ до вашого зображення.

Натомість загальною практикою є клонування git repo з-під докера у вашому інструменті CI на вибір, а просто COPYфайли у зображення. Це має другу перевагу: кешування докера. Докерне кешування розглядає запущену команду, змінні середовища, які вона включає, вхідні файли тощо, і якщо вони ідентичні попередній збірці з того ж батьківського кроку, вона повторно використовує попередній кеш. З git cloneкомандою сама команда ідентична, тому докер повторно використовувати кеш, навіть якщо зовнішній git repo буде змінено. Однак COPYкоманда розгляне файли в контексті збірки і зможе побачити, чи вони ідентичні чи оновлені, і використовувати кеш лише тоді, коли це доречно.


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

FROM ubuntu as clone

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git
# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Copy over private key, and set permissions
# Warning! Anyone who gets their hands on this image will be able
# to retrieve this private key file from the corresponding image layer
COPY id_rsa /root/.ssh/id_rsa

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

FROM ubuntu as release
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

COPY --from=clone /repo /repo
...

Зовсім недавно BuildKit перевіряє деякі експериментальні функції, які дозволяють передати ключ ssh як гору, який ніколи не записується на зображення:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git

# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN --mount=type=secret,id=ssh_id,target=/root/.ssh/id_rsa \
    git clone git@bitbucket.org:User/repo.git

І ви можете побудувати це за допомогою:

$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
  --secret id=ssh_id,src=$(pwd)/id_rsa .

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


BuildKit також додав функцію тільки для ssh, яка дозволяє вам все-таки захищати паролем ssh-ключі, результат виглядає так:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git

# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN --mount=type=ssh \
    git clone git@bitbucket.org:User/repo.git

І ви можете побудувати це за допомогою:

$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
  --ssh default=$SSH_AUTH_SOCK .

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


Щоб змусити докер виконувати git cloneнавіть ті, коли рядки раніше були кешовані, ви можете ввести ARG збірки, який змінюється з кожною збіркою, щоб зламати кеш. Це виглядає так:

# inject a datestamp arg which is treated as an environment variable and
# will break the cache for the next RUN command
ARG DATE_STAMP
# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

Тоді ви вводите цей змінний аргумент у команду docker build:

date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .

Ви пропонуєте використовувати git за межами Докера, проте ви поясните, як в будь-якому випадку боротися з ключами ssh. Коли ви вважаєте це необхідним / відповідним?
JCarlosR

2
@JCarlosR, коли у вас немає зовнішньої системи, в якій можна запустити збірку (наприклад, система CI / CD, здатна запустити клон заздалегідь). Винятки можуть бути, але клон всередині Dockerfile - запах коду.
BMitch

1

Вищевикладені рішення не працювали для бітбукета. Я подумав, що це робить трюк:

RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts \
    && eval `ssh-agent` \
    && ssh-add ~/.ssh/[key] \
    && git clone git@bitbucket.org:[team]/[repo].git
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.