在macOS上使用ssh-agent与docker

37
我想使用ssh-agent将我的密钥转发到docker镜像中,并从私有github仓库拉取代码。
我正在使用稍微修改过的版本https://github.com/phusion/passenger-docker,在Yosemite上使用boot2docker。
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的权限是什么? - seanmcl
8个回答

26

自从版本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),而不是像在Linux主机上那样使用$SSH_AUTH_SOCK环境变量中包含的路径。

2
经过更深入的挖掘:我认为只有容器内部的用户是root才能正常工作(否则他无法访问虚拟机中的套接字)。 - Denis R.
3
在我的Mac OS Big Sur上,没有/run/host-services这样的路径。为什么?我需要安装什么吗? - Salivan
2
@Salivan,我自己也没有这个路径。这是一个“神奇”的挂载 - 当docker看到它时,它知道如何处理这个路径。你试过了吗? - Jakub Kukul
1
@JakubKukul 是的,它有效了。为什么没有任何文档记录呢?或者至少我的谷歌无法找到提到这个的文档。 - Salivan
2
@Salivan 理想情况下这应该有文档记录,是的。我是通过关注此 Github 问题的线程才发现的:https://github.com/docker/for-mac/issues/410 - Jakub Kukul
1
以下是今天的文档 https://docs.docker.com/desktop/networking/#ssh-agent-forwarding - Alessandro Fazzi

7

1
这看起来非常有前途,但是在OS X上我得到了Permission denied(publickey)错误。也许这是因为在非Linux主机上,Docker在自己的WM中运行? - Tad Lispy

4

我扩展了@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-ssh中,执行chmod +x,并使用docker-run-ssh代替docker run

3
我创建了一个与docker-machine兼容的版本,因为Docker不推荐使用boot2docker。https://gist.github.com/leedm777/923706741c8296869e7d - leedm777
1
Dave - 你尝试过在docker-compose中使用这个吗?不确定如何修改你的示例以使其与在docker-compose.yml中静态定义的环境变量一起工作。 - Bryce

1
我遇到了类似的问题,通过在主模式下使用带控制套接字的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会话要好得多。


同时,最新版的Docker出现了问题: docker: 守护进程错误响应:无效的卷规范“:/ssh-agent”:无效的卷规范:‘:/ssh-agent’。 - aholbreich

1

对于我来说,在OSX Mavericks和docker 1.5上访问ssh-agent以转发密钥的方法如下:

  1. ssh into the boot2docker VM with boot2docker ssh -A. Don't forget to use option -A which enables forwarding of the authentication agent connection.

  2. Inside the boot2docker ssh session:

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

这个会话必须保持打开状态。请注意 SSH_AUTH_SOCK 环境变量的值。

  1. In another OS X terminal issue the docker run command with the SSH_AUTH_SOCK value from step 2 as follows:

    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会话才能使这个工作正常,但在找到更好的解决方案之前,至少对我来说这个方法可行。


1

目前在OS X上无法使用Socket转发。这里是@henrjk答案的一个变体,使用现在已经过时的boot2docker替换为Docker for Mac

  1. First run a ssh server in the container, with /tmp being on the exportable volume. Like this

     docker run -v tmp:/tmp -v \
     ${HOME}/.ssh/id_rsa.pub:/root/.ssh/authorized_keys:ro \
     -d -p 2222:22 arvindr226/alpine-ssh
    
  2. Then ssh into this container with agent forwarding

     ssh -A -p 2222 root@localhost
    
  3. Inside of that ssh session find out the current socket for ssh-agent

     3f53fa1f5452:~# echo $SSH_AUTH_SOCK
     /tmp/ssh-9zjJcSa3DM/agent.7
    
  4. Now you can run your real container. Just make sure to replace the value of SSH_AUTH_SOCK below, with the value you got in the step above

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

截至2022年8月,仍然可以在Docker Desktop for Mac上使用,并且可以使用capistrano代理转发来部署Rails 7应用程序。 - millisami

0

默认情况下,boot2docker 仅共享 /Users 下的文件。 SSH_AUTH_SOCK 可能位于 /tmp 下,因此 -v 挂载的是 VM 的代理,而不是您 Mac 上的代理。

如果您设置了 VirtualBox 共享 /tmp,它应该可以正常工作。


这听起来很有前途,你能提供更多关于如何做到这一点的信息吗?我找到了这个链接:https://github.com/boot2docker/boot2docker#virtualbox-guest-additions 但是我对Docker还比较新。 - Paul Odeon
打开你的虚拟机,右键点击boo2docker vm,选择设置,共享目录,点击添加按钮,输入/tmp,勾选自动挂载和永久性。但是,在测试后发现,共享目录不允许您共享套接字,所以它将无法工作。 - creack
1
我认为这是不可能的。SSH_AUTH_SOCK 是一个 Unix 套接字,而不是文件,因此它不能像文件那样与 VirtualBox 共享。 - David Resnick

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接