git - 如何从 Docker 容器克隆 Git 存储库
问题描述
我们有一个工具需要克隆几个 Git 存储库来聚合文档数据。我们希望将该工具放入 Docker 容器中,以便在本地和使用 Jenkins 轻松运行它,并实现可重复性。
Git 存储库托管在需要使用 SSH 密钥进行身份验证的私有服务器上。因此,Docker 容器必须以某种方式访问运行容器的用户的 SSH 密钥。
我们有一个约束列表:
- 我们不想在 Docker 镜像中嵌入 SSH 密钥
- 我们不希望用户构建 Docker 镜像。我们认为 a
Dockerfile
不能实现可重复性,而已经生成的 Docker 映像可以 - 我们不希望容器以
root
用户身份运行 - 我们想使用运行容器的主机用户的 SSH 密钥
- 参数可以提供给启动容器的命令(
-v
,-u
, ...)
问题:如果可能的话,我们怎样才能做到这一点?
有关的:
- 在 docker 容器中使用 SSH 密钥(SSH 密钥在构建时传递 - 我们想要运行时)
- 使用 dockerfile 克隆私有 git repo(同样的问题)
- 使用 Docker Compose (运行方式
root
)将主机的 SSH 密钥注入 Docker 机器
解决方案
你可以使用类似的东西:
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
确保我们在一个可以写入的目录中工作(我们也可以挂载一个我们具有读/写权限的卷或使用这样的目录构建映像)-v $HOME/.ssh:/path/to/.ssh
从主机挂载本地用户 SSH 密钥--entrypoint sh
并且-it
特定于alpine/git
进行交互式 shell 会话,您的图像可能不需要它
为什么要挂载假/etc/passwd
文件?
当您运行具有未知 UID/GID(不存在于 中)的基于 linux 的容器(例如alpine
或)时,命令可能会导致错误并显示如下消息:debian
/etc/passwd
git clone
Cloning into 'myrepo'...
No user exists for uid 1000
fatal: Could not read from remote repository.
通过挂载这个“假”密码文件,我们确保操作系统能够识别运行容器的用户并允许我们的 git clone 命令工作。我们的密码文件将如下所示:
git-user:x:1000:1000:Git User:/tmp:/bin/bash
大致意思是:
git-user
存在 UID 1000 和 GID 1000- 它的 HOME 目录是
/tmp
(它是可选的,但是这个目录是可写的并且避免了一些警告git clone
)
通过设置/tmp
(或可能在映像构建期间创建的另一个目录),我们确保我们有一个可写的 HOME 目录,git-user
该目录将防止警告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"
推荐阅读
- node.js - nodejs express server api - 大量请求 - 事件循环卡住了吗?
- ngrx - 如何使用 withLatestFrom 运算符在 Effects 中获取存储状态
- sql-server - TypeORM 处理数据库中断
- jira - Jira 结构 - 在公式列中显示问题链接类型
- javascript - 如何从嵌套数组中删除空元素
- master-data-management - Stibo Step Search 业务规则
- python - 如何在 Python 中正确使用 e(欧勒号)和 log 函数?
- android - AdMob 导致:无法获取提供程序 com.google.android.gms.ads.MobileAdsInitProvider: java.lang.ClassNotFoundException
- c# - 数据从 UI 移动到数据库时的路由差异(C# 到 SQL 服务器,浮动?到浮动)
- angular - 类型“ArtistDetailsComponent”上不存在属性“艺术家”。类型“ArtistDetailsComponent”