首页 > 编程知识 正文

docker映射容器目录到宿主机,docker和宿主机系统不一致

时间:2023-05-06 19:01:23 阅读:59502 作者:3782

我们最近做了一个envoy代理,使用envoyproxy/envoy:latest镜像进行本地测试,但遇到代理失败的情况,我们将记录整个进程。

配置代理参考了envoyproxy官方前端代理的样例配置作为蓝本,并将其更改为自己的配置。 内容如下。

static _ resources : listeners :-address : socket _ address 3360 address 3360.0.0 port _ value 33609901 filt tor tion _ manager typed _ config : ' @ type ' 3360 type.googleapis.com envoy.extensions.filters.net work.http _ cons 3360 autostat name : local _ route virtual _ hosts :-name : back end domains :-' * ' routes :-match : prefix ' route : cluster 3360 service1 http _ filters 3360-name : envoy.filters.http.router clusters 3360-name 3360 service ect robin load _ assignment 3360 cluster _ name 3360 service1 end points 3360-lb dress : socket _ address : address 3360127.0.0 . log_path3360/tmp/admin _ access.log address 3360 socket _ address : address :0.0 port _ value 33608001 layered _ runtime 3360 layered ce _ limits : listener : example _ listener _ name 3360 connection _ limit 336010000

容器的启动命令如下:

$ docker run-d---RM---name envoy-p 990133609901-p 800133608001-v/config/path/in/host/test.YAML 3360

upstream服务逻辑请求转发到本机8000端口,upstream在go中实现,代码简单,回显hello world,同时打印请求header

包管理器(' flag ' ' fmt ' ' net/http ' ' strings ' ' time ' ) funcgreet ) whttp.responsewriter,r * http.rresponse v :=ranger.header { varheaderstringfor _,v 13360=' } header=strings.trim right (header,',') fmt.printf

port", ":8000", "-port=:8000")flag.Parse()http.HandleFunc("/", greet)if err := http.ListenAndServe(port, nil); err != nil {fmt.Println(err.Error())}}

一切就绪,运行服务,开始测试

现象

通过本机curl请求,发现提示无法连接到上游主机

$ curl http://localhost:9901/upstream connect error or disconnect/reset before headers. reset reason: connection failure 分析

初步判断是由于容器的网络隔离,无法访问宿主机导致的。遂docker exec -it envoy /mgdgs/bash,安装网络包后,请求8000端口,是不通的,验证了网络隔离的猜测。

上网查了一下,在Stack Overflow的这个回答下,针对不同的操作系统环境,给出了不同的解决方案。但是这里首先要理解一下docker的network参数

network参数

network参数常见可选值有none、host、bridge
none:fkdmla,禁用容器网络,这个时候容器无法访问外部网络,外部也无法访问容器,你的-p参数也会被忽略
bridge:桥接,也是默认模式,容器会与宿主进行桥接,通过一个桥接的docker0网卡进行通信
host:即撤销网络隔离,这个模式下,你不需要要指定-p参数,容器内监听什么端口,就直接会绑定到宿主的同一端口上,这时容器和宿主是没有隔离的

在综合考虑之后,host模式虽然可以解决问题,但不是我想要的,必要的隔离还是需要的,所以优选bridge模式。
对于bridge模式,在linux环境下,docker deamon会创建一个docker0的网卡,用作网桥,实现容器和宿主的通信,但mac系统下隔离技术与linux不同,所以并不会创建这个网卡。

因为bridge是默认的网络选项,我们不需要修改docker启动命令。
那么mac上如何从容器内访问宿主的服务呢?

mac系统容器访问宿主

我本机安装了Docker desktop for mac,自带docker deamon。版本是3.6.0,内置docker engine是20.10.8。
在17.12版本之前,可以通过host名docker.for.mac.localhost来访问宿主,17.12版本及以后,可以通过docker.for.mac.host.internal来访问宿主。
登录到容器内通过ping进行验证如下:

root@eed301853eb6:/# ping docker.for.mac.localhostPING docker.for.mac.localhost (192.168.65.2) 56(84) bytes of data.64 bytes from 192.168.65.2: icmp_seq=1 ttl=37 time=4.02 ms64 bytes from 192.168.65.2: icmp_seq=2 ttl=37 time=0.361 ms^C--- docker.for.mac.localhost ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1001msrtt min/avg/max/mdev = 0.361/2.191/4.022/1.831 msroot@eed301853eb6:/# ping docker.for.mac.host.internalPING docker.for.mac.host.internal (192.168.65.2) 56(84) bytes of data.64 bytes from 192.168.65.2: icmp_seq=1 ttl=37 time=1.31 ms64 bytes from 192.168.65.2: icmp_seq=2 ttl=37 time=1.55 ms^C--- docker.for.mac.host.internal ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1002msrtt min/avg/max/mdev = 1.310/1.433/1.556/0.123 ms

其中解析IP地址就是我的本机地址

调整envoy配置

根据以上分析,调整envoy配置中clusters下的上游主机地址,将127.0.0.1替换为docker.for.mac.localhost或docker.for.mac.host.internal,即可实现代理对宿主机的访问。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。