使用dockerfile克隆私有git repo

问题描述 投票:210回答:7

我已经复制了这个代码,似乎是各种工作的dockerfiles,这是我的:

FROM ubuntu

MAINTAINER Luke Crooks "[email protected]"

# 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 [email protected]:Pumalo/docker-conf.git /home/docker-conf

这给了我错误

Step 10 : RUN git clone [email protected]: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 [email protected]: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

遗憾的是,这也行不通。

git bitbucket docker
7个回答
275
投票

我的密钥是受密码保护的,导致问题,下面列出了一个工作文件(为了未来的googlers的帮助)

FROM ubuntu

MAINTAINER Luke Crooks "[email protected]"

# 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 [email protected]:User/repo.git

86
投票

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

  1. 使用ssh-keygen -q -t rsa -N '' -f repo-key生成ssh密钥,它将为您提供repo-key和repo-key.pub文件。
  2. 将repo-key.pub添加到存储库部署密钥。 在GitHub上,转到[您的存储库] - >设置 - >部署密钥
  3. 将这样的内容添加到Dockerfile: 添加repo-key / RUN \ 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。虽然我可能在上面的一个答案中更喜欢使用ssh-keyscan的解决方案。


62
投票

没有必要摆弄ssh配置。使用包含环境变量的配置文件(不是Dockerfile),并在运行时使用shell脚本更新docker文件。您将令牌保留在Dockerfiles之外,您可以克隆https(无需生成或传递ssh密钥)。

Settings > Personal Access Tokens

  • 生成启用了repo范围的个人访问令牌。
  • 像这样克隆:git clone https://[email protected]/user-or-org/repo

一些评论者指出,如果您使用共享的Dockerfile,这可能会将您的访问密钥暴露给项目中的其他人。虽然这可能是或可能不是您特定用例的问题,但您可以通过以下方式处理:

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

16
投票

对于bitbucket存储库,生成应用程序密码(Bitbucket设置 - >访问管理 - >应用程序密码,请参阅图像),具有对repo和项目的读访问权限。

bitbucket user menu

然后你应该使用的命令是:

git clone https://username:[email protected]/reponame/projectname.git

16
投票

另一种选择是使用多阶段docker构建来确保SSH密钥不包含在最终映像中。

如我的post中所述,您可以准备具有所需依赖关系的中间图像到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 [email protected]: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)

1
投票

以上解决方案不适用于bitbucket。我认为这样做的诀窍:

RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts \
    && eval `ssh-agent` \
    && ssh-add ~/.ssh/[key] \
    && git clone [email protected]:[team]/[repo].git

1
投票

您通常不希望在docker构建中执行私有仓库的git clone。在那里进行克隆涉及将私有ssh凭证放在图像中,以后可以由有权访问您图像的任何人提取它们。

相反,通常的做法是在您选择的CI工具中克隆来自docker外部的git repo,并简单地将文件COPY放入图像中。这有第二个好处:docker缓存。 Docker缓存查看正在运行的命令,它包含的环境变量,输入文件等,如果它们与来自同一父步骤的先前构建相同,则它会重用该先前的缓存。使用git clone命令,命令本身是相同的,因此即使外部git repo被更改,docker也将重用缓存。但是,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 [email protected]:User/repo.git

FROM ubuntu as release
LABEL maintainer="Luke Crooks <[email protected]>"

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

最近,BuildKit一直在测试一些实验性功能,这些功能允许您将ssh密钥作为一个永远不会写入映像的挂载传递:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <[email protected]>"

# 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 [email protected]: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 <[email protected]>"

# 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 [email protected]: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 [email protected]:User/repo.git

然后在docker build命令中注入更改arg:

date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .
© www.soinside.com 2019 - 2024. All rights reserved.