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

时间:2019-06-07 09:15:05

标签: git docker ssh-keys

我们有一个工具,需要克隆几个Git存储库以汇总文档数据。我们希望将该工具放在Docker容器中,以便在本地和Jenkins轻松运行它,并实现可重复性。

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

我们有一个约束列表:

  1. 我们要在Docker映像中嵌入SSH密钥
  2. 我们不希望用户构建Docker映像。我们认为Dockerfile不能实现可重复性,而已经生成的Docker镜像可以做到
  3. 我们不希望容器以root用户的身份运行
  4. 我们想要使用运行容器的主机用户的SSH密钥
  5. 可以向启动容器的命令提供参数
  6. -v-u等)

问题:如果可能,我们如何实现?

相关:

2 个答案:

答案 0 :(得分:11)

您可以使用类似的内容:

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运行,从而能够在不更改其权限或使用根权限的情况下读取密钥。详细信息:

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

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

运行带有未知UID / GID(alpine中不存在的UID / GID)的基于Linux的容器(例如debian/etc/passwd)时,{{1} }命令可能会导致错误,并显示以下消息:

git clone

通过装入此“伪” passwd文件,我们确保操作系统将识别正在运行容器的用户,并允许我们的git clone命令起作用。我们的密码文件如下所示:

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

大致意思是

  • git-user:x:1000:1000:Git User:/tmp:/bin/bash 存在UID 1000和GID 1000
  • 它的HOME目录是git-user(它是可选的,但是该目录是可写的,并且避免来自/tmp的警告)

通过设置git clone(或在映像构建过程中可能创建的其他目录),我们确保我们为/tmp建立了可写的HOME目录,这将防止git-user发出警告,指出可以没有创建git clone目录

但是,如果您打算对容器运行其他任务,则可能会有其他副作用。

为什么使用.ssh

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

在示例中,我使用git clone 但可能不安全,另一种解决方案是使用git repo服务器主机密钥在容器中挂载一个已知的主机文件,并使用{{ 1}}

答案 1 :(得分:2)

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

例如:

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

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