Home > Back-end >  Access host from within a docker container
Access host from within a docker container

Time:11-18

I have a dockerized app and I use the following docker-compose.yml to run it:

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. I would like my php service to be able to access it.

I found people suggesting to add to following to my php service configuration:

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. I have the same error when I try to curl http://host.docker.internal:3000.

I desperatly tried to add a port mapping to the php container:

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.

I also tried to add

network_mode: host

But it fails because I already have a 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.

Any help appreciated, thanks in advance!

CodePudding user response:

Make sure you are using version of docker that supports host.docker.internal. If you are using linux version, then 20.10 supports it. For other systems you should probably consult documentation and probably some issues on github of docker-for-linux / other projects OS revelant.

After that...

Make sure extra_hosts is direct child of php service:

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.

Make sure that your service on port 3000 is working properly and there is no firewall issue.

Remember that localhost means always local ip from current container point of view. It means that localhost inside container maps to local container IP and not your host machine IP. This is a reason for sending extra_hosts section.

Also docker.host.internal is not your host loopback interface. 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.

You can check what service is listening on which interface / ip address running following command on your host machine: netstat -tulpn

This should return something like following 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 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
  • Related