docker和docker compose中使用host.docker.internal访问其他服务

在使用 docker 过程中,如果我们要访问宿主机,最直接的办法是查到 docker0ip 然后在docker中直接访问即可。

使用host.docker.internal

无host.docker.internal的情况

比如我们有一个 nginx 的容器,需要反向代理主机上的 8081 端口的一个服务。

linux 下使用 ip addr 命令查到的 docker0 大概是这样的:

...
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c2:6b:7b:52 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c2ff:fe6b:7b52/64 scope link 
       valid_lft forever preferred_lft forever
...

可以看到, docker0 网关的地址是 172.17.0.1 那么我们的 nginx 配置可以这么写:

upstream some_service {
    server 172.17.0.1:8081;
}

server {
    listen 9091 ssl;

    location / {
        proxy_pass http://some_service;
        proxy_set_header Host              $http_host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
    }
}

这么做大部分情况下是行得通的,但是如果刚好你的某个配置使用了 172.17 网段,或者你的服务器不是那么常见的发行版, docker 网关就不一定是这个了,就需要再去确定它的地址,再去修改一遍所有使用主机服务的地方,这样显然不够环保。

在docker中使用host.docker.internal

还好,在docker 20.10 版本就开始支持在Linux上使用host.docker.internal

以下示例使用版本:

Docker version 24.0.7, build afdd53b
Docker Compose version v2.23.3

运行一个容器验证一下:

docker run -it --add-host=host.docker.internal:host-gateway nginx cat /etc/hosts

127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.1  host.docker.internal
172.21.0.2  a348e1bfb96f

可以看到 host.docker.internal 正确的解析到了 172.17.0.1 上,那么上面的 nginx 配置就可以改成:

upstream some_service {
    server host.docker.internal:8081;
}

重启 nginx 容器后发现是一切正常。

在docker compose中使用host.docker.internal

docker compose 中使用 host.docker.internal 是通过 extra_hosts 来指定的,比如刚才的 nginx 使用的 docker-compose.yml

version: '3.8'

services:
    nginx:
        image: nginx:latest
        container_name: nginx
        ports:
            - ${NGINX_PORTS}:${NGINX_PORTS}
        volumes:
            - ${NGINX_DIR}/conf/nginx.conf:/etc/nginx/nginx.conf
            - ${NGINX_DIR}/conf/conf.d:/etc/nginx/conf.d
            - ${NGINX_DIR}/logs:/var/log/nginx
            - ${NGINX_DIR}/ca:/etc/nginx/ca
            - ${NGINX_WWWROOT}:/usr/share/nginx/html
        extra_hosts:
            - "host.docker.internal:host-gateway"
            - "router:192.168.0.1"
        restart: always

这样的效果和上面的 --add-host 方式是一样的效果。

小彩蛋

上面的 docker-compose.ymlextra_hosts 下有一行 router:192.168.0.1 这个是干嘛的呢?恩,这个其实是使用 nginx 代理路由器 web 管理的,是的,除了可以添加宿主机上的服务,也可以添加网络可达的其他主机上的服务,加上内网穿透后,就可以愉快的使用 https 在外网的访问内网的路由器了。

标题:docker和docker compose中使用host.docker.internal访问其他服务

原文链接:https://beltxman.com/4257.html

若无特殊说明本站内容为 行星带 原创,未经同意请勿转载。

发表评论

您的电子邮箱地址不会被公开。

Scroll to top