使用ubuntu tusty,在远程计算机上运行一项服务,我可以通过localhost:9999
的ssh隧道通过端口转发进行访问。
我有一个docker容器正在运行。我需要通过主机的隧道从容器内访问该远程服务。
我尝试使用-L 9000:host-ip:9999
从容器隧道传输到主机,然后从容器内通过127.0.0.1:9000
访问服务无法连接。为了检查端口映射是否打开,我试过了
nc -luv -p 9999 # at host
nc -luv -p 9000 # at container
跟随this, parag. 2,但即使在做的时候也没有感知到的沟通
容器上的
nc -luv host-ip -p 9000
我还尝试通过docker run -p 9999:9000
映射端口,但是报告绑定失败,因为主机端口已经在使用中(可能是从主机隧道到远程计算机)。
所以我的问题是
1 - 如何实现连接?我是否需要为主机设置ssh隧道,或者仅通过docker端口映射实现这一点?
2 - 测试连接的快速方法是什么?通过bash,最好是。
感谢。
答案 0 :(得分:13)
我认为你可以通过在你的docker run中添加--net=host
来实现。但另请参阅此问题:Forward host port to docker container
答案 1 :(得分:9)
通过--net=host
或通过network_mode: host
在docker-compose中将主机网络用作容器的网络是一种选择,但这会带来不想要的副作用,即(a)您现在将容器端口暴露在您的主机系统;(b)您无法再连接到那些未映射到您的主机网络的容器。
对于您而言,一种更快捷,更清洁的解决方案是使ssh隧道可用于主机系统(即docker0
网桥),而不是将docker容器暴露在主机环境中(如已接受的建议)答案)。
设置隧道:
为此,请通过以下方式检索您的docker0
网桥使用的IP:
ifconfig
您将看到类似这样的内容:
docker0 Link encap:Ethernet HWaddr 03:41:4a:26:b7:31
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
现在,您需要告诉ssh bind to this ip来监听通过9000端口定向的流量
ssh -L 172.17.0.1:9000:host-ip:9999
如果不设置 bind_address ,:9000
将only可用于主机的环回接口,而本身不适用于Docker容器。
旁注:您还可以将隧道绑定到0.0.0.0
,这将使ssh侦听所有接口。
设置您的应用程序:
在您的容器化应用程序中,使用相同的docker0
ip连接到服务器:172.17.0.1:9000
。现在,通过docker0
网桥路由的流量也将到达ssh隧道:)
例如,如果您有一个“ DOT.NET Core”应用程序需要连接到位于:9000
的远程数据库,则您的“ ConnectionString”将包含"server=172.17.0.1,9000;
。
答案 2 :(得分:3)
在MacOS上(在v19.03.2
中进行了测试)
1)在主机上创建隧道
ssh -i key.pem username@jump_server -L 3336:mysql_host:3306 -N
2)从容器中,您可以使用host.docker.internal
或docker.for.mac.localhost
或docker.for.mac.host.internal
来引用主机。
示例
mysql -h host.docker.internal -P 3336 -u admin -p
note from docker-for-mac official doc
我想从主机连接到主机上的服务
主机的IP地址正在更改(如果没有网络访问权限,则没有IP地址)。 从18.03开始,我们建议您连接到特殊的DNS 名称
host.docker.internal
,解析为内部IP地址 由主机使用。 这是出于发展目的,不适用于 用于Mac的Docker Desktop之外的生产环境。网关也可以通过
gateway.docker.internal
访问。
答案 3 :(得分:2)
我想分享我的解决方案。我的情况如下:我的主机上有一个PostgreSQL SSH隧道,我需要堆栈中的一个容器通过它连接到数据库。
我花了数小时试图找到解决方案(Ubuntu + Docker 19.03),但失败了。与其对newReq, err = http.NewRequest("PUT", signedurl, file)
client = &http.Client{}
res, err = client.Do(newReq)
进行巫术魔术,不如对Docker引擎本身的设置进行修改,我想出了一个解决方案,但令我震惊的是,我之前没有想到这一点。最重要的是我不想使用iptables
模式:安全第一。
我没有尝试允许容器与主机进行通信,而是向堆栈中添加了另一个服务,该服务将创建隧道,因此其他容器可以轻松进行通信,而不会受到黑客攻击。
在我的host
中配置主机后:
~/.ssh/config
并将服务添加到堆栈:
Host project-postgres-tunnel
HostName remote.server.host
User sshuser
Port 2200
ForwardAgent yes
TCPKeepAlive yes
ConnectTimeout 5
ServerAliveCountMax 10
ServerAliveInterval 15
PHP容器开始通过隧道通信,没有任何问题:
postgres:
image: cagataygurturk/docker-ssh-tunnel:0.0.1
volumes:
- $HOME/.ssh:/root/ssh:ro
environment:
TUNNEL_HOST: project-postgres-tunnel
REMOTE_HOST: localhost
LOCAL_PORT: 5432
REMOTE_PORT: 5432
# uncomment if you wish to access the tunnel on the host
#ports:
# - 5432:5432
请记住,如果尚未将公钥放入该主机中,则:
postgresql://user:password@postgres/db?serverVersion=11&charset=utf8
我非常确定,无论使用哪种操作系统(MacOS / Linux),它都能正常工作。
答案 4 :(得分:1)
我对Ubuntu 18.04的2美分-一个非常简单的答案,不需要额外的隧道,额外的容器,额外的docker选项或暴露主机。
简单来说,在创建反向隧道时,请确保ssh绑定到所有接口,因为默认情况下,它将仅将反向隧道的端口绑定到localhost。例如,在腻子中,确保已选中选项Connection-> SSH-> Tunnels Remote ports do the same (SSH-2 only)
。
这或多或少等同于为隧道的远程部分指定绑定地址0.0.0.0
(更多详细信息here):
-R [bind_address:]port:host:hostport
但是,这对我不起作用,除非我允许,我的sshd服务器配置中的GatewayPorts
选项。非常感谢Stefan Seidel出色的answer。
简而言之:(1)将反向隧道绑定到0.0.0.0,(2)让sshd服务器接受此类隧道。
完成此操作后,我可以通过docker网关172.17.0.1
和绑定到主机的端口从docker容器访问我的远程服务器。
答案 5 :(得分:1)
我同意@hlobit的观点,即@ B12Toaster答案应该是公认的答案。
万一有人遇到此问题,但在SSH隧道上的设置稍有不同,这是我的发现。就我而言,不是使用ssh -L
创建从Docker主机到远程计算机的隧道,而是使用ssh -L
创建了从远程计算机到Docker主机的远程转发SSH隧道。
在此设置中,默认情况下sshd不允许网关端口,即,在Docker主机上的文件/etc/ssh/sshd_config
中,GatewayPorts no
应当不加注释并设置为GatewayPorts yes
或{{1} }。我配置了GatewayPorts clientspecified
,并通过GatewayPorts clientspecified
配置了远程转发SSH隧道。记住在更改ssh -L 172.17.0.1:dockerHostPort:localhost:sshClientPort user@dockerHost
(/etc/ssh/sshd_config
)之后重新启动sshd。
您的Docker容器应该能够连接到sudo systemctl restart sshd
上的Docker主机,这反过来又被隧穿回SSH客户端的172.17.0.1:dockerHostPort
。
参考:
答案 6 :(得分:0)
在我这方面,在Linux的Windows子系统(WSL v1)中运行Docker,我无法使用docker0连接方法。 host.docker.internal
也无法解析(最新的docker版本)。
但是,我发现我可以直接在docker容器中使用host-ip内部人员。
ipconfig
),例如192.168.0.5
docker exec -it d6b4be5b20f7 /bin/bash
apt-get update && apt-get install iputils-ping
ping 192.168.0.5
PING 192.168.0.5 (192.168.0.5) 56(84) bytes of data.
64 bytes from 192.168.0.5 : icmp_seq=1 ttl=37 time=2.17 ms
64 bytes from 192.168.0.5 : icmp_seq=2 ttl=37 time=1.44 ms
64 bytes from 192.168.0.5 : icmp_seq=3 ttl=37 time=1.68 ms
显然,在Windows中,您可以使用官方主机ip直接从容器内连接到主机。
答案 7 :(得分:0)
万一有人需要(就像我一样),Windows和WSL的解决方案与Mac OS提到的@prayagupd相同
使用您喜欢的工具或端口(例如3300)创建到远程服务的SSH隧道。
然后,您可以使用以下命令从Docker容器连接到隧道端口3300上的MySQL DB:
mysql -u user -p -h host.docker.internal -P 3300