在 macOS 上使用 ssh-agent 和 docker

Posted

技术标签:

【中文标题】在 macOS 上使用 ssh-agent 和 docker【英文标题】:Using ssh-agent with docker on macOS 【发布时间】:2015-01-18 03:46:21 【问题描述】:

我想使用 ssh-agent 将我的密钥转发到 docker 映像并从私有 github 存储库中提取。

我在 Yosemite 上使用带有 boot2docker 的 https://github.com/phusion/passenger-docker 的略微修改版本。

ssh-add -l
...key details
boot2docker up

然后我使用我在很多地方看到的命令(即https://gist.github.com/d11wtq/8699521):

docker run --rm -t -i -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent my_image /bin/bash

但它似乎不起作用:

root@299212f6fee3:/# ssh-add -l
Could not open a connection to your authentication agent.

root@299212f6fee3:/# eval `ssh-agent -s`
Agent pid 19

root@299212f6fee3:/# ssh-add -l
The agent has no identities.

root@299212f6fee3:/# ssh git@github.com
Warning: Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts.
Permission denied (publickey).

【问题讨论】:

文件$SSH_AUTH_SOCK的权限是什么? 【参考方案1】:

2.2.0.0 版本开始,macOS 的 docker 允许用户在容器中访问主机的 SSH 代理。

下面是一个示例命令,让您可以这样做:

docker run --rm -it \
-v /run/host-services/ssh-auth.sock:/ssh-agent \
-e SSH_AUTH_SOCK="/ssh-agent" \
my_image

请注意,您必须安装特定路径 (/run/host-services/ssh-auth.sock) 而不是 $SSH_AUTH_SOCK 环境变量中包含的路径,就像在 linux 主机上所做的那样。

【讨论】:

经过更多挖掘:我认为仅当容器内的用户是 root 时才有效(否则他无法访问 VM 中的套接字) 在我的 mac OS Big Sur 上没有这样的路径 /run/host-services。为什么?我应该安装一些东西吗? @Salivan 我自己也没有这条路。这是一个“神奇”的挂载 - docker 知道如何在看到这条路径时处理它。你试过了吗? @JakubKukul 是的,它奏效了。为什么没有在任何地方记录?或者至少我的谷歌无法找到提到这一点的文档。 @Salivan 理想情况下,这应该记录在某个地方,是的。我通过关注这个 Github 问题的线程发现了它:github.com/docker/for-mac/issues/410【参考方案2】:

单行:

以下是在运行 Debian Jessie 映像的 Ubuntu 16 上设置它的方法:

docker run --rm -it --name container_name \
-v $(dirname $SSH_AUTH_SOCK):$(dirname $SSH_AUTH_SOCK) \
-e SSH_AUTH_SOCK=$SSH_AUTH_SOCK my_image

https://techtip.tech.blog/2016/12/04/using-ssh-agent-forwarding-with-a-docker-container/

【讨论】:

这看起来很有希望,但在 OS X 上我收到了 Permission denied (publickey). 错误。可能是因为在非 Linux 主机上 Docker 在它自己的 WM 中运行?【参考方案3】:

我扩展了@wilwilson 的回答,并创建了一个脚本,用于在 OSX boot2docker 环境中设置代理转发。

https://gist.github.com/rcoup/53e8dee9f5ea27a51855

#!/bin/bash

# Use a unique ssh socket name per-invocation of this script
SSH_SOCK=boot2docker.$$.ssh.socket

# ssh into boot2docker with agent forwarding
ssh -i ~/.ssh/id_boot2docker \
    -o StrictHostKeyChecking=no \
    -o IdentitiesOnly=yes \
    -o UserKnownHostsFile=/dev/null \
    -o LogLevel=quiet \
    -p 2022 docker@localhost \
    -A -M -S $SSH_SOCK -f -n \
    tail -f /dev/null

# get the agent socket path from the boot2docker vm
B2D_AGENT_SOCK=$(ssh -S $SSH_SOCK docker@localhost echo \$SSH_AUTH_SOCK)

# mount the socket (from the boot2docker vm) onto the docker container
# and set the ssh agent environment variable so ssh tools pick it up
docker run \
    -v $B2D_AGENT_SOCK:/ssh-agent \
    -e "SSH_AUTH_SOCK=/ssh-agent" \
    "$@"

# we're done; kill off the boot2docker ssh agent
ssh -S $SSH_SOCK -O exit docker@localhost

把它贴在~/bin/docker-run-sshchmod +x里面,用docker-run-ssh代替docker run

【讨论】:

我创建了一个适用于 docker-machine 的版本,现在 Docker 建议不要使用 boot2docker。 gist.github.com/leedm777/923706741c8296869e7d dave - 你试过在 docker-compose 中使用它吗?不确定如何修改您的示例以使用 docker-compose.yml 中静态定义的环境变量。【参考方案4】:

我遇到了类似的问题,并且能够通过在主模式下使用带有控制套接字的 ssh 并将其全部包装在这样的脚本中使事情变得非常无缝:

#!/bin/sh   

ssh -i ~/.vagrant.d/insecure_private_key -p 2222 -A -M -S ssh.socket -f docker@127.0.0.1 tail -f /dev/null

HOST_SSH_AUTH_SOCK=$(ssh -S ssh.socket docker@127.0.0.1 env | grep "SSH_AUTH_SOCK" | cut -f 2 -d =)

docker run -v $HOST_SSH_AUTH_SOCK:/ssh-agent \
       -e "SSH_AUTH_SOCK=/ssh-agent" \
       -t hello-world "$@"

ssh -S ssh.socket -O exit docker@127.0.0.1

这不是世界上最漂亮的东西,但比手动保持 SSH 会话打开 IMO 要好得多。

【讨论】:

同时newes docker抱怨:docker:来自守护进程的错误响应:无效的卷规范“:/ssh-agent”:无效的卷规范:':/ssh-agent'。【参考方案5】:

对我来说,访问 ssh-agent 以转发在 OSX Mavericks 和 docker 1.5 上工作的密钥,如下所示:

    使用boot2docker ssh -A SSH 进入 boot2docker 虚拟机。不要忘记使用启用身份验证代理连接转发的选项 -A。

    在 boot2docker ssh 会话中:

    docker@boot2docker:~$ echo $SSH_AUTH_SOCK
    /tmp/ssh-BRLb99Y69U/agent.7750
    

此会话必须保持打开状态。记下 SSH_AUTH_SOCK 环境变量的值。

    在另一个 OS X 终端中,使用步骤 2 中的 SSH_AUTH_SOCK 值发出 docker run 命令,如下所示:

    docker run --rm -t -i \
      -v /tmp/ssh-BRLb99Y69U/agent.7750:/ssh-agent \
      -e SSH_AUTH_SOCK=/ssh-agent my_image /bin/bash
    root@600d0e9b443d:/# ssh-add -l
    2048 6c:8e:82:08:74:33:78:61:f9:9a:74:1b:65:46:be:eb         
    /Users/dev/.ssh/id_rsa (RSA)
    

我真的不喜欢我必须保持 boot2docker ssh 会话打开才能完成这项工作,但在找到更好的解决方案之前,这至少对我有用。

【讨论】:

【参考方案6】:

默认情况下,boot2docker 只共享/Users 下的文件。 SSH_AUTH_SOCK 可能在/tmp 之下,所以-v 挂载了VM 的代理,而不是你的mac 中的那个。

如果您将 VirtualBox 设置为共享 /tmp,它应该可以工作。

【讨论】:

这听起来很有希望,您能否提供更多有关如何执行此操作的信息?我发现了这个:github.com/boot2docker/boot2docker#virtualbox-guest-additions 但我对 docker 比较陌生 打开你的virtualbox,右击boo2docker vm,设置,共享目录,点击添加按钮,输入/tmp,勾选自动挂载和永久。但是,经过测试,共享目录似乎不允许你共享socket,所以它不起作用。 我认为这是不可能的。 SSH_AUTH_SOCK 是 Unix 套接字,而不是文件,因此不能像文件那样与 VirtualBox 共享。【参考方案7】:

套接字转发在 OS X 上还不能工作。这是使用 Docker for Mac 而不是现在已过时的 boot2docker 引入 2019 年的 @henrjk 答案的变体。

    首先在容器中运行 ssh 服务器,/tmp 位于可导出卷上。像这样

     docker run -v tmp:/tmp -v \
     $HOME/.ssh/id_rsa.pub:/root/.ssh/authorized_keys:ro \
     -d -p 2222:22 arvindr226/alpine-ssh
    

    然后通过代理转发 ssh 进入这个容器

     ssh -A -p 2222 root@localhost
    

    在该 ssh 会话中找出 ssh-agent 的当前套接字

     3f53fa1f5452:~# echo $SSH_AUTH_SOCK
     /tmp/ssh-9zjJcSa3DM/agent.7
    

    现在您可以运行真正的容器了。只需确保将下面的 SSH_AUTH_SOCK 的值替换为您在上述步骤中获得的值

     docker run -it -v tmp:/tmp  \
     -e SSH_AUTH_SOCK=/tmp/ssh-9zjJcSa3DM/agent.7 \
     vladistan/ansible
    

【讨论】:

【参考方案8】:

无法打开与您的身份验证代理的连接。

此错误occurs when $SSH_AUTH_SOCK env var 在主机上设置不正确或根本没有设置。您可以尝试各种解决方法。不过,我的建议是dual-boot Linux and macOS。

其他资源:

Using SSH keys inside docker container - 相关问题 SSH and docker-compose - 博文 Build secrets and SSH forwarding in Docker 18.09 - 博文

【讨论】:

以上是关于在 macOS 上使用 ssh-agent 和 docker的主要内容,如果未能解决你的问题,请参考以下文章

Linux之ssh-agent命令

在 Windows 10 上激活 ssh-agent 的 VSCode

Paramiko 在 Windows 上找不到来自 ssh-agent 的密钥

ssh-agent 和 crontab - 有没有让这些满足的好方法?

ssh-agent妙用

带有 openssh 密钥的 TortoiseGit 未使用 ssh-agent 进行身份验证