dockerfileでプライベートgitリポジトリを複製する


240

私は周りのさまざまな作業中のDockerfileのように見えるものからこのコードをコピーしました。これが私のものです。

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

私のキーはパスワードで保護されていたため、問題が発生しました。作業中のファイルが以下にリストされています(将来のGoogle社員の助けのため)

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
念のため、ここにキーのパスワード保護を解除する方法を説明するリンクがあります
Thomas

82
参考までに、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安全のために走るのが良いです。
fluidsonic 2015

5
誰かがランニングssh-keyscanが問題である理由を説明できますか?私の理解では、単にGithub / Bitbucketの公開鍵を取得するだけです。最終的にレイヤーにならないように、どのような代替案を使用できますか?
ペドロ

9
@Pedro特にキースキャン手順はまったく問題ではありません、あなたは明らかに正しいです。どちらかといえば、これらのホスト公開鍵は可能な限り拡散する必要があります。known_hostsファイルの詳細については、sshd(8)を参照してください。人々は十分に警戒しているように聞こえたとき、ただランダムに物事を賛成します。
2017

99

そのDockerイメージ用に新しいSSHキーセットを作成する必要があります。自分のプライベートキーをそこに埋め込むことはおそらく望ましくないからです。これを機能させるには、そのキーをgitリポジトリのデプロイメントキーに追加する必要があります。これが完全なレシピです:

  1. ssh-keygen -q -t rsa -N '' -f repo-keyrepo-keyおよびrepo-key.pubファイルを提供するSSH鍵を生成します。

  2. リポジトリデプロイメントキーにrepo-key.pubを追加します。
    GitHubで、[リポジトリ]-> [設定]-> [キーのデプロイ]に移動します

  3. Dockerfileに次のようなものを追加します。

    リポジトリキーを追加/
    実行\
      chmod 600 / repo-key && \  
      echo "IdentityFile / repo-key" >> / etc / ssh / ssh_config && \  
      echo -e "StrictHostKeyChecking no" >> / etc / ssh / ssh_config && \  
      //ここにgit cloneコマンド...
    

上記はStrictHostKeyCheckingをオフにするため、.ssh / known_hostsは必要ありません。上記の答えの1つで、おそらくssh-keyscanを使用したソリューションの方が好きです。


6
警告:私の設定では、echo -e "..."もファイル内に-eと書き込みます。フラグを削除するだけで正常に動作します。
コンキリカルター

あなたの答えは私が私の問題を解決するのを助ける上で絶対的に完璧でした。ありがとうございました!
デビッドポインター

私はまだ同じ問題を抱えています:fatal: Could not read from remote repository.
Alex

1
何百万人もありがとう!私はあなたに愛を宣言する縁にいます。あなたは私が数日間戦っていた問題を解決しました!
アレクサンドラ

この質問に対して選択された答えは、もはや良い答えではありません。2014年は正解でしたが、2020年はこれが正解です。
ビカルバスネット

70

ssh設定をいじる必要はありません。環境変数を含む構成ファイル(Dockerfileではなく)を使用し、シェルスクリプトで実行時にdockerファイルを更新します。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ます。つまり、onを置き換えるスクリプトを呼び出します。構成ファイル(.ymlまたは任意の形式)を使用して、環境変数を使用して同じことを行うこともできます。
  • そのプロジェクトのみのgithubユーザーを作成(およびアクセストークンを生成)

何の話をしているのSettings > Applications
ターボラディン2015

1
この方法の欠点は、Dockerfileとは別に保存されているキーを参照できる@crookseyの方法とは対照的に、Dockerfile内にプライベートリポジトリの資格情報を保存することです。OPがDockerfileを格納する方法に関するコンテキストがないと、これが問題を引き起こすかどうかを判断できませんが、個人的な経験から、DockerfileをVCS内に格納したいので、資格情報を含むも​​のをコミットしたくありません。Dockerが環境変数を渡してコマンドをビルドする機能を実装したら、これが最もクリーンなソリューションになることに同意します。
Jabbslad、2015年

2
@CalvinFroedgeローカルで私はあなたがあなたのホストを意味すると思いますか?ビルド時にホストの環境変数をコンテナーに公開する方法がわかりません。そのため、このgithub.com/docker/docker/issues/6822などの未解決の問題があります。明確にしていただけますか?
Jabbslad

1
よりクリーン(懸念の分離):クローンリポジトリのリンクボリューム+クローンタスク専用の専用コンテナー+ SSHキー(またはトークン)のみのリンクボリューム stackoverflow.com/a/30992047を参照してください。おそらく、stackoverflow.com / a / 29981990と組み合わせることができます。
Peterino、2015

9
また、問題はgithubリポジトリではなく、BITBUCKETリポジトリです。
Michael Draper

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)

ARG SSH_PRIVATE_KEYは、ARG SSH_KEYに置き換える必要があります
Joseph

git cloneが完了したら、キーを削除できませんか?
ブロンチャ

1
可能ですがRUN、前のイメージレイヤーにキーを残さないように、シングルの一部として行う必要があります。docker では、最終的な画像レイヤーのSSHキーを削除する実験的な引数を1.13使用することもできます。--squash
jaker

19

bitbucketリポジトリの場合は、リポジトリとプロジェクトへの読み取りアクセス権を持つアプリパスワード(Bitbucket設定->アクセス管理->アプリパスワード、画像を参照)を生成します。

bitbucketユーザーメニュー

次に、使用する必要があるコマンドは次のとおりです。

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

1
最も単純:)私はSSHベースのアプローチを好むことを認めなければなりませんが、上記のいずれも機能しませんでした...ファイルが見つかりませんなど
Janos

「アクセス管理」が表示されない...時代遅れだと思いますか?
Martin Thoma

1
働きました!シンプルでシンプルな...すごい!
Josemy、2018年

2
もちろん...左のバーのプロフィール写真をクリックし、次にBitbucket設定をクリックするだけで、次のようなものが表示されます。imgur.com
Josemy

1
これでうまくいきました。ただし、サブモジュールがあり、機能--recursiveしませんでした。私はgit cloneサブモジュールごとに配置する必要がありましたが、これは問題ありませんが、再帰的に機能する場合はすばらしいでしょう。
Zailyn Tamayo

13

git cloneDockerビルド内からプライベートリポジトリの実行を望まないことがよくあります。そこでクローンを行うには、プライベートssh資格情報をイメージ内に配置する必要があります。この資格情報は、後でイメージへのアクセス権を持つユーザーが抽出できます。

代わりに、一般的な方法は、選択したCIツールのdockerの外部からgitリポジトリを複製することです。 COPY、ファイルをイメージすることです。これには2番目の利点があります。Dockerキャッシングです。Dockerキャッシングは、実行中のコマンド、それに含まれる環境変数、入力ファイルなどを調べ、それらが同じ親ステップからの以前のビルドと同一である場合、以前のキャッシュを再利用します。ではgit clone、コマンド、コマンド自体は同じなので、ドッキングウィンドウは、外部の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キーが必要ですが、少なくとも1つのステージでビルドを実行し、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以前の行がキャッシュされている場合でもdockerに強制的に実行させるには、ビルドごとに変化するビルド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 .

Dockerの外部からgitを使用することをお勧めしますが、とにかくsshキーを処理する方法を説明します。これはいつ必要/適切だと思いますか?
JCarlosR

1
ビルドを実行する外部システムがない場合は@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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.