如何从 Docker 容器克隆 Git 存储库

How to clone a Git repository from a Docker container

我们有一个工具需要克隆几个 Git 存储库来聚合文档数据。我们想将该工具放入 Docker 容器中,以便在本地和 Jenkins 中轻松 运行 将其整合,并实现可重现性。

Git 存储库托管在需要使用 SSH 密钥进行身份验证的私人服务器上。因此,Docker 容器必须以某种方式获得对用户 运行 连接容器的 SSH 密钥的访问权。

我们有一个约束列表:

  1. 我们不想在Docker图像中嵌入SSH密钥
  2. 我们希望用户构建Docker图像。我们认为 Dockerfile 不能实现再现性,而已经生成的 Docker 图像可以实现
  3. 我们希望容器运行作为root用户
  4. 我们希望使用主机用户的 SSH 密钥运行连接容器
  5. 可以为启动容器的命令提供参数(-v-u、…)

问题:如果可能的话,我们怎样才能做到这一点?

相关:

您可以使用类似的东西:

echo "git-user:x:$(id -u):$(id -g):Git User:/tmp:/bin/bash" > /tmp/fake_passwd # See below why to use this
docker run \
   -u $(id -u):$(id -g) \
   -w /tmp \
   -v $HOME/.ssh:/path/to/.ssh \
   -v /tmp/fake_passwd:/etc/passwd  \
   --entrypoint sh \
   -it \
   alpine/git

  # commands in the container:
  $ export GIT_SSH_COMMAND='ssh -i /path/to/.ssh/id_rsa -o "StrictHostKeyChecking=no"'
  $ git clone [path to git repo]

这将确保容器 运行 与主机用户具有相同的 UID/GID,从而能够在不更改其权限或使用 root 权限的情况下读取密钥。详情:

  • -u $(id -u):$(id -g) 设置容器用户与主机用户匹配
  • -w /tmp 确保我们在可以写入的目录中工作(我们也可以挂载我们具有 read/write 权限的卷或使用此类目录构建映像)
  • -v $HOME/.ssh:/path/to/.ssh 从主机挂载本地用户 SSH 密钥
  • --entrypoint sh-it 特定于 alpine/git 以进行交互式 shell 会话,您的图像可能不需要它

为什么要挂载伪造的 /etc/passwd 文件?

当您 运行 将 linux-based 容器(例如 alpinedebian)与未知的 UID/GID(不存在于/etc/passwd), git clone 命令可能会导致错误并显示如下消息:

Cloning into 'myrepo'...
No user exists for uid 1000
fatal: Could not read from remote repository.

通过安装这个 "fake" passwd 文件,我们确保 OS 将识别用户 运行 容器并允许我们的 git 克隆命令工作。我们的密码文件将如下所示:

git-user:x:1000:1000:Git User:/tmp:/bin/bash

大致意思是:

  • git-user 存在 UID 1000 和 GID 1000
  • 它的 HOME 目录是 /tmp(它是可选的,但这个目录是可写的,避免来自 git clone 的一些警告)

通过设置 /tmp(或在映像构建期间可能创建的另一个目录),我们确保我们有一个用于 git-user 的可写 HOME 目录,这将防止来自 git clone 的警告说它无法创建 .ssh 目录

但是,如果您打算 运行 使用容器执行不同的任务,这可能会产生其他副作用。

为什么要使用 GIT_SSH_COMMAND

GIT_SSH_COMMAND='ssh -i /path/to/.ssh/id_rsa' 将确保 git clone 使用我们的密钥,但这也可以使用 ssh-agent 来完成 - 请参阅 https://serverfault.com/questions/447028/non-interactive-git-clone-ssh-fingerprint-prompt

在示例中我使用 -o "StrictHostKeyChecking=no" 但它可能不安全,另一种解决方案是使用 git repo 服务器主机密钥并使用 -o "UserKnownHostsFile=/path/to/KnownHostFile"

在主机上克隆存储库并将目录安装到 docker 映像中可以吗?

例如:

git clone github:repo1
git clone github:repo2
  ...

docker run -v repo1:/path/to/repo1 -v repo2:/path/to/repo2 ...