使用dockerfile克隆私有git repo

cro*_*sey 219 git bitbucket docker

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

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
Run Code Online (Sandbox Code Playgroud)

这给了我错误

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
Run Code Online (Sandbox Code Playgroud)

这是我第一次使用dockerfiles,但是从我读过的(并从工作配置中获取)我不明白为什么这不起作用.

我的id_rsa与我的dockerfile位于同一个文件夹中,是我本地密钥的副本,可以克隆此repo没问题.

编辑:

在我的dockerfile中,我可以添加:

RUN cat /root/.ssh/id_rsa
Run Code Online (Sandbox Code Playgroud)

它会打印出正确的密钥,因此我知道它被正确复制了.

我也试着做,因为诺亚建议并跑:

RUN echo "Host bitbucket.org\n\tIdentityFile /root/.ssh/id_rsa\n\tStrictHostKeyChecking no" >> /etc/ssh/ssh_config
Run Code Online (Sandbox Code Playgroud)

遗憾的是,这也行不通.

cro*_*sey 283

我的密钥受密码保护,导致问题,下面列出了一个工作文件(为了未来的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
Run Code Online (Sandbox Code Playgroud)

  • 只是一个FYI,运行RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts后,Image会将其保存为图层.如果有人抓住你的图像,他们可以检索密钥......即使你在后面的图层中删除了该文件,当你添加它时,他们可以回到步骤7. (78认同)
  • 谢谢你的回答.但对于我们来说,构建失败是随机的,经过调查后我们注意到`ssh-keyscan`的默认超时时间为5秒,而bitbucket经常超过.`ssh-keyscan`甚至不报错.所以最好运行`RUN ssh-keyscan -T 60 bitbucket.org >>/root/.ssh/known_hosts`是安全的. (23认同)
  • 以防万一,这里是一个[link](http://learninglamp.wordpress.com/2012/06/26/remove-passphrase-from-ssh-key/),描述了如何删除密钥的密码保护 (11认同)
  • @Pedro密钥扫描步骤尤其不是问题,你显然是对的.如果有的话,这些主机公钥应该尽可能地传播.有关`known_hosts`文件的详细信息,请参阅sshd(8).当人们发出足够惊人的声音时,他们就会对随机事物进行投票. (7认同)
  • 有人可以解释为什么运行`ssh-keyscan`是个问题吗?我的理解是它只会拉出Github/Bitbucket的公钥.可以使用什么替代方案,以便它不会在一个层中结束? (5认同)
  • 这将使任何有权访问docker镜像的人都可以访问私钥 - 即使你添加了`RUN rm/root/.ssh/id_rsa`.这似乎是一个很大的问题,有些人可能没有想到,应该在你的答案中提到. (3认同)
  • 所有这些应该在一个层中运行,并且/root/.ssh应该在该层的末尾被删除.小改进:无需触摸known_hosts,只需使用>而不是>>,您不需要追加. (2认同)
  • @GabeRoux我发现“docker build”进程会抱怨“ADD”或任何其他命令尝试访问父目录或以上目录中的任何内容。下到孩子就好了。我最终将“docker build”包装到 shell 脚本中以准备、构建和运行。 (2认同)
  • @EnchanterIO Docker映像是分层构建的。每个层都可以单独访问。RUN rm /root/.ssh/id_rsa只会在删除密钥的情况下创建一个新层,但是仍然存在的上一层不会被删除。当您运行docker build时,它会为每个图层打印一个ID,然后您可以docker run该ID并读取密钥。 (2认同)

Mar*_*n R 90

您应该为该Docker镜像创建新的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:

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

请注意,上面关闭StrictHostKeyChecking,因此您不需要.ssh/known_hosts.虽然我可能在上面的一个答案中更喜欢使用ssh-keyscan的解决方案.

  • 警告:在我的配置上,echo -e"..."也在文件中写入-e.只需删除标志,它就可以正常工作. (6认同)
  • 当您在映像中共享生产 ssh 密钥时,这会在您的存储库中留下安全漏洞 (4认同)
  • 谢谢百万!我正处于向你表白的边缘。你解决了我纠结了好几天的问题! (2认同)
  • 为此问题选择的答案不再是一个好的答案。这在 2014 年是正确的,但在 2020 年这是正确的答案。 (2认同)

Cal*_*dge 67

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

转到设置>个人访问令牌

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

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

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

  • 还有一个问题是BITBUCKET回购,而不是github回购. (9认同)
  • @CalvinFroedge在当地我认为你的意思是你的主人?我不知道在构建时将主机上的环境变量暴露给容器的方法,这就是为什么我们有这样的开放问题https://github.com/docker/docker/issues/6822.请你澄清一下吗? (2认同)
  • 这不是一个安全的解决方案,无论您如何存储凭证(无论是在秘密、环境变量等中)`git clone https://MY_TOKEN@github.com/user-or-org/repo`会出现在图像历史记录中并会泄露您的 PAT。 (2认同)

jak*_*ker 20

另一种选择是使用多阶段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
Run Code Online (Sandbox Code Playgroud)

然后我们可以建立:

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

证明我们的SSH密钥已经消失:

docker run -ti --rm clone-example cat /root/.ssh/id_rsa
Run Code Online (Sandbox Code Playgroud)

从构建机器清理中间图像:

docker rmi -f $(docker images -q --filter label=stage=intermediate)
Run Code Online (Sandbox Code Playgroud)


Nom*_*mce 17

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

bitbucket用户菜单

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

git clone https://username:generated_password@bitbucket.org/reponame/projectname.git
Run Code Online (Sandbox Code Playgroud)

  • 当然......您只需点击左侧栏上的个人资料图片,然后点击*Bitbucket设置*,您将看到如下内容:https://imgur.com/EI33zj3 (2认同)

Jer*_*kar 11

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

这是从一开始的完整过程:

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

  2. 在 git 提供商网站(gitlab、github..)添加生成的公钥(.pub 扩展名)

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

eval $(ssh-agent)
ssh-add /path/to/your/private/key
Run Code Online (Sandbox Code Playgroud)
  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
Run Code Online (Sandbox Code Playgroud)
  1. 现在你终于可以构建你的 Dockerfile (启用了 buildkit)
DOCKER_BUILDKIT=1 docker build . --ssh default
Run Code Online (Sandbox Code Playgroud)

由于您当前无法传递控制台参数以在 docker-compose 中构建,因此该解决方案尚不适用于 docker-compose,但应该很快就会可用(它已在 github 上完成并建议作为合并请求)


BMi*_*tch 6

您通常不希望git clone在docker构建中执行私有回购。在此处进行克隆涉及将私有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 git@bitbucket.org:User/repo.git

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

COPY --from=clone /repo /repo
...
Run Code Online (Sandbox Code Playgroud)

最近,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
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令进行构建:

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

请注意,这仍然要求您的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
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令进行构建:

$ 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 .
Run Code Online (Sandbox Code Playgroud)

再次,将其注入到构建中,而无需写入图像层,从而消除了证书可能意外泄漏的风险。


要强制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
Run Code Online (Sandbox Code Playgroud)

然后将变化的arg注入docker build命令中:

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

  • @BMitch Dockerfile 中私有存储库的“git clone”可能不仅仅是代码味道,它可能是直接的安全风险。我认为值得一提的是,“git clone https://{{MY_TOKEN}}@github.com”的答案都是错误的,因为即使你以某种方式将克隆命令隐藏在秘密或其他东西中,PAT仍然会是存在于克隆存储库的远程属性中。所以感谢您的回答,它提供了非常好的信息。我认为“复制”以前下载的 tarball(未在 Dockerfile 中下载)是我的解决方案。 (5认同)
  • @JCarlosR,当您没有外部系统来运行构建时(例如能够提前运行克隆的 CI/CD 系统)。可能有例外,但 Dockerfile 内的克隆是一种代码味道。 (3认同)
  • 您建议从 Docker 外部使用 git,但是您仍然解释了如何处理 ssh 密钥。您什么时候认为这是必要/适当的? (2认同)
  • @LukAron,这表明 CI 系统正在被复杂的 Dockerfile 取代,并导致许多问题,例如泄露秘密和破坏 Docker 的缓存逻辑。这有点像回答如何定义全局变量的问题,是的,有一个答案,但大多数寻找答案的人应该真正考虑是否需要依赖注入。两者的实施都需要更多工作,但对于大多数用例而言,它们是更好的解决方案。 (2认同)