简体   繁体   English

从 docker 容器内访问主机

[英]Access host from within a docker container

I have a dockerized app and I use the following docker-compose.yml to run it:我有一个 dockerized 应用程序,我使用以下 docker-compose.yml 来运行它:

version: '3.1'

services:
    db:
        image: mysql:5.7
        ports:
            - "3306:3306"
        env_file:
            - ./docker/db/.env
        volumes:
            - ./docker/db/data:/var/lib/mysql:rw
            - ./docker/db/config:/etc/mysql/conf.d
        command: mysqld --sql_mode="NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

    php:
        build: ./docker/php/7.4/
        volumes:
            - ./docker/php/app.ini:/usr/local/etc/php/conf.d/docker-php-ext-app.ini:ro
            - ./docker/logs/app:/var/www/app/var/log:cached
            - .:/var/www/app:cached
        working_dir: /var/www/app
        links:
            - db
        env_file:
            - ./docker/php/.env

    webserver:
        image: nginx:1
        depends_on:
            - php
        volumes:
            - ./docker/webserver/app.conf:/etc/nginx/conf.d/default.conf:ro
            - ./docker/logs/webserver/:/var/log/nginx:cached
            - .:/var/www/app:ro
        ports:
            - "80:80"

I have a server that is not dockerized runing on my machine, I can access it via localhost:3000 .我的机器上没有运行 dockerized 的服务器,我可以通过localhost:3000访问它。 I would like my php service to be able to access it.我希望我的php服务能够访问它。

I found people suggesting to add to following to my php service configuration:我发现有人建议在我的php服务配置中添加以下内容:

extra_hosts:
    - "host.docker.internal:host-gateway"

But when I add this, then docker-compose up -d and try docker exec -ti php_1 curl http://localhost:3000 , I get curl: (7) Failed to connect to localhost port 3000 after 0 ms: Connection refused . But when I add this, then docker-compose up -d and try docker exec -ti php_1 curl http://localhost:3000 , I get curl: (7) Failed to connect to localhost port 3000 after 0 ms: Connection refused . I have the same error when I try to curl http://host.docker.internal:3000 .当我尝试curl http://host.docker.internal:3000时,我遇到了同样的错误。

I desperatly tried to add a port mapping to the php container:我拼命尝试将端口映射添加到php容器:

ports:
    - 3000:3000

But then when I start the services I have the following error:但是当我启动服务时,出现以下错误:

ERROR: for php_1  Cannot start service php: driver failed programming external connectivity on endpoint php_1 (9dacd567ee97b9a46699969f9704899b04ed0b61b32ff55c67c27cb6867b7cef): Error starting userland proxy: listen tcp4 0.0.0.0:3000: bind: address already in use

ERROR: for php  Cannot start service php: driver failed programming external connectivity on endpoint php_1 (9dacd567ee97b9a46699969f9704899b04ed0b61b32ff55c67c27cb6867b7cef): Error starting userland proxy: listen tcp4 0.0.0.0:3000: bind: address already in use

Which is obvious since my server is running on that 3000 port.这很明显,因为我的服务器在3000端口上运行。

I also tried to add我也尝试添加

network_mode: host

But it fails because I already have a links .但它失败了,因为我已经有一个links I get the following error:我收到以下错误:

Cannot create container for service php: conflicting options: host type networking can't be used with links.

I am running docker v20.10.6 on Ubuntu 21.10.我在 Ubuntu 21.10 上运行 docker v20.10.6。

Any help appreciated, thanks in advance!任何帮助表示赞赏,在此先感谢!

Make sure you are using version of docker that supports host.docker.internal.确保您使用的 docker 版本支持 host.docker.internal。 If you are using linux version, then 20.10+ supports it.如果您使用的是 linux 版本,则 20.10+ 支持。 For other systems you should probably consult documentation and probably some issues on github of docker-for-linux / other projects OS revelant.对于其他系统,您可能应该查阅有关 docker-for-linux / 其他项目操作系统相关的 github 的文档和一些问题。

After that...在那之后...

Make sure extra_hosts is direct child of php service:确保 extra_hosts 是 php 服务的直接子节点:

php:
    extra_hosts:
        host.docker.internal: host-gateway
    build: ./docker/php/7.4/

Try using ping host.docker.internal first to check whether your host machine responds correctly.首先尝试使用ping host.docker.internal来检查您的主机是否正确响应。

Make sure that your service on port 3000 is working properly and there is no firewall issue.确保端口 3000 上的服务正常工作并且没有防火墙问题。

Remember that localhost means always local ip from current container point of view.请记住,从当前容器的角度来看, localhost始终意味着本地 ip。 It means that localhost inside container maps to local container IP and not your host machine IP.这意味着容器内的localhost映射到本地容器 IP 而不是您的主机 IP。 This is a reason for sending extra_hosts section.这是发送 extra_hosts 部分的原因。

Also docker.host.internal is not your host loopback interface. docker.host.internal 也不是您的主机环回接口。 If service you are trying to reach listens only on localhost interface then there is no chance to reach it without doing some magic with iptables / firewall.如果您尝试访问的服务仅在 localhost 接口上侦听,那么如果不使用 iptables / 防火墙做一些魔术,就没有机会访问它。

You can check what service is listening on which interface / ip address running following command on your host machine: netstat -tulpn您可以检查哪个服务正在侦听哪个接口/ip 地址在您的主机上运行以下命令: netstat -tulpn

This should return something like following output:这应该返回类似于 output 的内容:

$ netstat -tulpn
(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:39195           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 ::1:631                 :::*                    LISTEN      -                   

From docker container I can reach services listening on 0.0.0.0 (all interfaces) but cannot access 631 port as it is only on 127.0.0.1从 docker 容器中,我可以访问在 0.0.0.0(所有接口)上侦听的服务,但无法访问 631 端口,因为它仅在 127.0.0.1 上

$ docker run --rm -it --add-host="host.docker.internal:host-gateway" busybox
/ # ping host.docker.internal
PING host.docker.internal (172.17.0.1): 56 data bytes
64 bytes from 172.17.0.1: seq=0 ttl=64 time=0.124 ms
64 bytes from 172.17.0.1: seq=1 ttl=64 time=0.060 ms
^C
--- host.docker.internal ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.060/0.092/0.124 ms
/ # telnet host.docker.internal 631
telnet: can't connect to remote host (172.17.0.1): Connection refused
/ # telnet host.docker.internal 22
Connected to host.docker.internal
SSH-2.0-OpenSSH_8.6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM