用dockerfile克隆私有git repo

我从周围的各种工作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在同一个文件夹中,是我的本地密钥的副本,可以克隆这个repo没有问题。

编辑:

在我的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

不幸的是,这也行不通。

364083 次浏览

我的密钥是密码保护,这是导致问题的原因,一个工作文件现在列出如下(为未来的谷歌人提供帮助)

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

您应该为Docker映像创建新的SSH密钥集,因为您可能不想在其中嵌入您自己的私钥。要使其工作,您必须将该密钥添加到git存储库中的部署密钥中。以下是完整的食谱:

  1. ssh-keygen -q -t rsa -N '' -f repo-key生成ssh密钥,它会给你repo-key和repo-key。酒吧的文件。

  2. <李> < p >添加repo-key。
    . Pub到存储库部署密钥 在GitHub上,进入[你的存储库]->设置->部署键

  3. 在Dockerfile中添加如下内容:

    ADD repo-key /
    RUN \
    chmod 600 /repo-key && \
    echo "IdentityFile /repo-key" >> /etc/ssh/ssh_config && \
    echo -e "StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \
    // your git clone commands here...
    

Note that above switches off StrictHostKeyChecking, so you don't need .ssh/known_hosts. Although I probably like more the solution with ssh-keyscan in one of the answers above.

没有必要摆弄ssh配置。使用包含环境变量的配置文件(不是Dockerfile),并让shell脚本在运行时更新docker文件。你可以在dockerfile中保留令牌,并且可以通过https进行克隆(不需要生成或传递ssh密钥)。

设置>个人访问令牌

  • 生成一个启用repo作用域的个人访问令牌。
  • 像这样克隆:git clone https://MY_TOKEN@github.com/user-or-org/repo

一些评论者指出,如果您使用共享Dockerfile,这可能会将您的访问密钥暴露给项目中的其他人。虽然这可能是也可能不是你的特定用例所关心的问题,这里有一些你可以处理的方法:

  • 使用shell脚本接受参数,这些参数可能包含作为变量的键。将Dockerfile中的一个变量替换为sed或类似的变量,即使用sh rundocker.sh MYTOKEN=foo调用脚本,将替换为https://\{\{MY_TOKEN}}@github.com/user-or-org/repo。请注意,您也可以使用配置文件(.yml或任何您想要的格式)来完成相同的任务,但是使用环境变量。
  • 仅为该项目创建一个github用户(并生成一个访问令牌)

对于bitbucket存储库,生成应用程序密码(bitbucket设置->访问管理->应用程序密码,见图片),具有对repo和project的读访问权限。

bitbucket user menu

那么你应该使用的命令是:

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

另一种选择是使用多级docker构建,以确保您的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)

你通常不希望在docker构建中执行私有回购的git clone。在这里进行克隆需要将私有ssh凭证放在映像中,以便稍后由访问映像的任何人提取它们。

相反,常见的做法是从docker外部的CI工具中克隆git repo,并简单地COPY文件到映像中。这还有第二个好处:docker缓存。Docker缓存会查看正在运行的命令、它包含的环境变量、输入文件等,如果它们与来自同一父步骤的前一个构建相同,它就会重用之前的缓存。对于git clone命令,命令本身是相同的,因此即使外部git repo被更改,docker也将重用缓存。然而,COPY命令将查看构建上下文中的文件,并查看它们是否相同或是否已更新,并仅在适当的时候使用缓存。

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 .

同样,它被注入到构建中,而从未写入映像层,从而消除了凭据可能意外泄漏的风险。


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凭据成为映像的一部分。


如果您打算将凭据添加到构建中,请考虑使用多阶段构建来执行此操作,并且只将这些凭据放置在早期阶段,并且永远不会标记和推送到构建主机之外。结果如下所示:

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
...

为了强制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 build命令中注入更改参数:

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

对于其他人搜索我有同样的问题,添加--ssh default标志使它工作

现在你可以在构建容器时使用Buildkit选项--ssh default;在构建之前,您需要将SSH部署密钥添加到SSH -agent。

以下是从头开始的完整流程:

  1. 在部署服务器上创建密钥对。只需运行ssh-keygen -t ecdsa将密钥对存储到~/.ssh

  2. 添加您的公钥生成(。Pub扩展)在你的git提供商网站(gitlab, github..)

  3. 将你的密钥添加到你的< >强ssh-agent < / >强(一个基本上管理密钥比处理每个文件更容易的程序)

eval $(ssh-agent)
ssh-add /path/to/your/private/key
  1. 把这个添加到Dockerfile中:
# this 3 first lines add your provider public keys to known_host
# so git doesn't get an error from SSH.


RUN mkdir -m 700 /root/.ssh && \
touch -m 600 /root/.ssh/known_hosts && \
ssh-keyscan your-git-provider.com > /root/.ssh/known_hosts




# now you can clone with --mount=type=ssh option,
# forwarding to Docker your host ssh agent


RUN mkdir -p /wherever/you/want/to/clone && cd /wherever/you/want/to/clone && \
--mount=type=ssh git clone git@gitlab.com:your-project.git
  1. 现在你终于可以构建Dockerfile了(启用buildkit)
DOCKER_BUILDKIT=1 docker build . --ssh default

因为你目前不能通过控制台参数来构建docker-compose,这个解决方案还不能用于docker-compose,但应该很快就可以了(它已经在github上完成了,并作为合并请求提出)

附注:这个解决方案是快速的;简单;但是以降低安全性为代价(参见@jrh的评论)。


创建一个访问令牌:https://github.com/settings/tokens

将其作为参数传递给docker (注:如果你正在使用CapRover,将它设置在App Configs下)

在Dockerfile中:

ARG GITHUB_TOKEN=${GITHUB_TOKEN}
RUN git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
RUN pip install -r requirements.txt

附注:这里假设私有回购在requirements.txt中是以下格式:

git+https://github.com/<YOUR-USERNAME>/<YOUR-REPO>.git

除了@Calvin Froedge使用个人访问令牌(PAT)的方法之外,

你可能需要在你的PAT之前添加oauthoauth2作为用户名,像这样进行身份验证:

https://oauth:<token>@git-url.com/user/repo.git

最近在Rust项目中的私有存储库中遇到了类似的问题。 我建议完全避免ssh权限/config

而不是:

  1. 在构建环境中克隆存储库,例如CI,其中权限已经存在(或可以轻松配置)
  2. 将文件复制到Dockerfile中(也可以在CI中本地缓存)

例子

第一部分,CI内部

CARGO_HOME=tmp-home cargo fetch

part 2)在Dockerfile中

COPY tmp-home $CARGO_HOME

不管哪种语言/包系统,这个过程都是相同的