鱼喃

听!布鲁布鲁,大鱼又在那叨叨了

无需端口映射,实现外部网络访问Docker集群内部服务

如何访问容器内并没有向外开放的服务呢?

背景

Docker支持端口映射,即将主机的某一端口映射到容器的端口,这样对主机这一端口的请求就会被转发到容器内,实现外部网络与容器通信的目的。
之前在部署Apache Storm系统的时候,发现web管理页里的supervisor日志无法查看,它的地址是类似storm_supervisor:8000这种形式的,而外部主机根本无法解析这个地址,即使可以解析(10.x.x.x),网络也是不互通的,无法访问。如果采取端口映射方式,一方面需要在外部主机上修改host文件,十分麻烦;另一方面,每一个supervisor都需要映射相同的端口,会造成冲突。所以这种方式无法实现,只能考虑其他方式。

解决方案

某日,突然想起来自己平时用的fq方式:ssh转socks5。而且,更加完美的是,socks5默认支持远程dns解析,这样连host文件都不用改了。
说干就干,首先要找到一个安装了ssh服务的镜像(一般情况下,镜像都没有这个服务),很可惜,没有找到合适的。那就只能自己做了,也不难,就一条安装命令。

制作镜像

编写Dockerfile

1
2
3
4
5
6
7
8
9
FROM ubuntu
RUN apt update \
&& apt install -y openssh-server

RUN ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
RUN cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

ADD bootstrap.sh /etc/bootstrap.sh
CMD ["bash", "/etc/bootstrap.sh"]

push到github上,再通过docker平台build即可。本地构建镜像也是可以的,不过这样跨机就找不到镜像了。

加上启动脚本

bootstrap.sh

1
2
3
4
#! /bin/bash

/etc/init.d/ssh start
ssh -t -t -D 0.0.0.0:7001 -o StrictHostKeyChecking=no localhost

解释:
1、先启动ssh服务
2、连接localhost生成socks5代理,加上StrictHostKeyChecking=no参数直接信任对方的指纹,不然连接不会建立。

启动docker容器

这个镜像我已经做好了,上面的步骤只是作为介绍,不需要再重新走一遍,直接运行下面这条命令即可。
–network需要根据实际情况修改,这个命令可以代理swarm-net网络中的服务

1
2
3
4
5
6
docker service create \
--replicas 1 \
--name proxy_docker \
--network swarm-net \
-p 7001:7001 \
newnius/docker-proxy

测试

尽管一条telnet命令即可测试是否奏效,但我们的目的是为了能在浏览器上访问web服务,那就以这个为例。

浏览器插件安装

chrome、firefox等浏览器默认可以直接设置socks5代理,但是我们并不是每次都只访问容器内部服务。虽然不安装插件不影响访问互联网,但是速度上会有明显的延迟,再说了,我们还要愉快的fq呢。安装一个自动切换代理插件可以很好的解决这个问题。
Chrome上的插件是SwitchyOmega,firefox上是AutoProxy(?),安装和配置过程我就不写了,网上类似教程很多。

配置

端口写7001,协议是socks5

访问内部服务

在地址栏输入:storm_ui:8080 应该就能看到熟悉的storm ui了。(前提是你部署了storm,如果没有,装一个apache也可以测试)

相关Dockerfile和配置见:newnius/Dockerfiles