Клонировать приватный репозиторий git с помощью dockerfile

240

Я скопировал этот код из того, что похоже на различные рабочие файлы Docker, вот мое:

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

К сожалению, это тоже не работает.

crooksey
источник

Ответы:

300

Мой ключ был защищен паролем, что вызывало проблему, рабочий файл теперь указан ниже (для помощи будущим гуглерам)

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
crooksey
источник
11
На всякий случай, вот ссылка, описывающая, как снять защиту паролем ключа
Thomas
82
Просто для справки: после запуска RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts изображение будет сохранено в виде слоя. Если кто-то завладеет вашим изображением, он может получить ключ ... даже если вы удалите этот файл на более позднем слое, b / c они могут вернуться к шагу 7, когда вы добавили его.
Берни Перес
23
Спасибо за полезный ответ. Но для нас сборка была случайной, и после исследования мы заметили, что ssh-keyscanпо умолчанию установлен таймаут в 5 секунд, который часто превышал битбакет. ssh-keyscanдаже не сообщит об ошибке. Так что лучше беги, RUN ssh-keyscan -T 60 bitbucket.org >> /root/.ssh/known_hostsчтобы быть в безопасности.
Fluidsonic
5
Может кто-нибудь объяснить, почему бег ssh-keyscanэто проблема? Насколько я понимаю, он просто вытянет открытый ключ Github / Bitbucket. Какую альтернативу можно использовать, чтобы она не оказалась в слое?
Педро
9
@Pedro В частности, шаг сканирования клавиш не является проблемой, вы совершенно правы. Во всяком случае, эти открытые ключи хоста должны распространяться как можно больше. Смотрите sshd (8) для получения подробной информации о known_hostsфайле. Люди просто высказывают случайные вещи, когда они звучат достаточно тревожно.
тнэ
99

Вам следует создать новый набор ключей SSH для этого образа Docker, так как вы, вероятно, не хотите вставлять туда свой собственный закрытый ключ. Чтобы он работал, вам нужно добавить этот ключ к ключам развертывания в вашем 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 no" >> / etc / ssh / ssh_config && \  
      // ваши команды git clone здесь ...
    

Обратите внимание, что выше отключает StrictHostKeyChecking, поэтому вам не нужно .ssh / known_hosts. Хотя мне, вероятно, больше нравится решение с ssh-keyscan в одном из ответов выше.

Марцин Р
источник
6
Предупреждение: в моей конфигурации echo -e "..." также напишите -e внутри файла. Просто уберите флаг, и он отлично работает.
Conchylicultor
Ваш ответ был абсолютно идеальным, помогая мне решить мою проблему. Спасибо!
Дэвид Пойнтер
У меня все еще та же проблема:fatal: Could not read from remote repository.
Алекс
1
Спасибо миллионам! Я на грани признания в любви к тебе. Вы решили проблему, с которой я боролся в течение нескольких дней!
Александра
Ответ, выбранный для этого вопроса, больше не является хорошим ответом. Это было правильно в 2014 году, но для 2020 года это правильный ответ.
Бикаль Баснет
71

Там нет необходимости возиться с конфигурациями SSH. Используйте файл конфигурации (не файл Docker), который содержит переменные среды, и попросите сценарий оболочки обновить файл Docker во время выполнения. Вы храните токены в своих файлах Docker и можете клонировать через 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 (и сгенерировать токен доступа) только для этого проекта
Calvin Froedge
источник
В каком контексте вы говорите Settings > Applications?
Турболад
1
Недостатком этого подхода является то, что вы храните учетные данные для частного репо в Dockerfile, в отличие от подхода @ crooksey, который позволит вам ссылаться на ключ, который хранится отдельно от Dockerfile. Без контекста о том, как OP хранит Dockerfile, мы не можем определить, вызовет ли это проблему, но из личного опыта я предпочитаю хранить свои Dockerfile в VCS и не хочу фиксировать что-либо, содержащее учетные данные. Как только Docker реализует возможность передавать переменные env в команду build, я согласен, что это будет самое чистое решение.
Jabbslad
2
@CalvinFroedge локально Я предполагаю, что вы имеете в виду своего хозяина? Мне не известен способ предоставления переменных среды на хосте контейнеру во время сборки, поэтому у нас есть такие открытые проблемы, как github.com/docker/docker/issues/6822 . Пожалуйста, вы можете уточнить?
Jabbslad
1
Еще чище (разделение задач): связанный том для клонированного репо + выделенный контейнер только для задачи клонирования + связанный том только с ключами SSH (или токеном, как вы предлагаете). См. Stackoverflow.com/a/30992047 , возможно, в сочетании со stackoverflow.com/a/29981990 .
Петерино
9
Также вопрос для репозитория BITBUCKET, а не репозитория github.
Майкл Дрэйпер
25

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

Как описано в моем посте, вы можете подготовить ваше промежуточное изображение с необходимыми зависимостями для git clone, а затем 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)
jaker
источник
ARG SSH_PRIVATE_KEY необходимо заменить на ARG SSH_KEY
Джозеф Перси
мы не можем просто удалить ключи после того, как git clone сделан?
Бронча
1
Вы могли бы сделать, но вам нужно сделать это как часть одного, RUNчтобы вы не оставили ключ в предыдущем слое изображения. По состоянию на докер1.13 вы можете использовать --squash экспериментальный аргумент, который также удалит ключ SSH в ваших окончательных слоях изображения.
Джекер
19

Для репозитория bitbucket сгенерируйте пароль приложения (настройки Bitbucket -> Управление доступом -> Пароль приложения, см. Изображение) с доступом для чтения к репозиторию и проекту.

пользовательское меню bitbucket

Тогда команда, которую вы должны использовать:

git clone https://username:generated_password@bitbucket.org/reponame/projectname.git
Nomce
источник
1
Проще всего :) Я должен признать, что предпочел бы подход, основанный на SSH, но я не мог заставить работать все вышеперечисленное ... файлы не найдены и т. Д.
Janos
Я не вижу "Управление доступом" ... Я думаю, что оно устарело?
Мартин Тома
1
Работал! Просто и понятно ... Отлично!
Джозем
2
Конечно ... Вы только должны нажать на свое фото профиля на левой панели, а затем на настройках Bitbucket , и вы увидите что - то вроде этого: imgur.com/EI33zj3
Josemy
1
Это сработало для меня. Однако у меня есть подмодули и --recursiveне работает. Я должен был вставить git cloneдля каждого подмодуля, что хорошо, но было бы здорово, если бы он работал рекурсивно.
Зайлин Тамайо
14

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

Вместо этого обычной практикой является клонирование git-репозитория из-за пределов докера в выбранном вами инструменте CI и просто COPYфайлы в образ. Это имеет второе преимущество: кэширование докера. Кэширование Docker проверяет выполняемую команду, включенные в нее переменные среды, входные файлы и т. Д., И если они идентичны предыдущей сборке из того же родительского шага, он использует этот предыдущий кэш. Сgit clone команды сама команда идентична, поэтому docker будет повторно использовать кэш, даже если внешнее git-репо изменилось. Тем не менее, 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 .

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


Чтобы заставить docker запускать 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:

date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .
BMitch
источник
Вы предлагаете использовать git извне Docker, однако в любом случае объясняете, как обращаться с ssh-ключами. Когда вы считаете это необходимым / уместным?
JCarlosR
2
@JCarlosR, когда у вас нет внешней системы для запуска сборки (например, система CI / CD, способная заранее запускать клон). Могут быть исключения, но клон внутри Dockerfile - это запах кода.
BMitch
1

Вышеуказанные решения не работали для bitbucket. Я подумал, что это делает трюк:

RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts \
    && eval `ssh-agent` \
    && ssh-add ~/.ssh/[key] \
    && git clone git@bitbucket.org:[team]/[repo].git
tvgriek
источник