skip to Main Content

I’m trying to connect to host OS MySQL via host.docker.internal, I’m able to connect if i directly mention my internal IP in Laravel application hosted inside docker container.

OS / ENVIRONMENT:
Host operating system and version: MacOS Monterey 12.5.1
Docker desktop version: 4.12.0 (85629)
Docker desktop engine: Engine: 20.10.17
Docker desktop compose version: v2.10.2

Problem:
These are the steps i took to connect my Laravel application inside docker to my host OS MySQL. I successfully managed to connect my application via internal IP address of my Host OS, but the internal IP keep changing and its kind of getting dificult to keep changing the DB_HOST inside laravel .env each time the IP change. so i want to use host.docker.internal but i won’t work.

Steps:

1: docker-compose down (Delete all the containers)

2: I removed the devilbox .env port HOST_PORT_MYSQL=

3: I changed the port of my host OS MySQL to 3306 and using sequel ace i successfully connected to mysql with these credentials

Host: 127.0.0.1
user: root
database: hanger
port: 3306

4: In order to connect from docker to my Host OS MySQL i had to edit my my.cnf file OR in this case created a new one for MySQL here the my.cnf

[mysqld]
bind_address = 0.0.0.0 # default is 127.0.0.1 Change to 0.0.0.0 to allow remote connections

5: Restarted the MySQL server and confirmed that MySQL can now listen to all IP’s and NOT just localhost

6: used this command

netstat -anp tcp | grep 3306 OR netstat -ap tcp | grep -i "listen"

tcp4 0 0 127.0.0.1.3306 127.0.0.1.52469 ESTABLISHED
tcp4 0 0 127.0.0.1.52469 127.0.0.1.3306 ESTABLISHED
tcp4 0 0 127.0.0.1.3306 127.0.0.1.52468 ESTABLISHED
tcp4 0 0 127.0.0.1.52468 127.0.0.1.3306 ESTABLISHED
tcp4 0 0 127.0.0.1.3306 127.0.0.1.52464 ESTABLISHED
tcp4 0 0 127.0.0.1.52464 127.0.0.1.3306 ESTABLISHED
tcp4 0 0 *.3306 . LISTEN
tcp46 0 0 *.33060 . LISTEN
tcp4 0 0 192.168.18.190.3306 192.168.18.190.52566 TIME_WAIT
tcp4 0 0 192.168.18.190.3306 192.168.18.190.52567 TIME_WAIT
tcp4 0 0 192.168.18.190.3306 192.168.18.190.52568 TIME_WAIT

7: Once its confirmed that 3306 is listeing need to create a MySQL user which would be connected from other than localhost

8: In mysql shell i executed these queries, since I’m using MySQL 8.0.27 the creating user and granting previliges must be in seperate queries.

CREATE USER 'root'@'%' IDENTIFIED BY 'root'; // remember this root password we will use it in Laravel .env
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

9: To make sure the root@% user is created type

SELECT User, Host FROM mysql.user; there are two root users one with host set to localhost and second one is %

10: Now its time to Edit Laravel .env MySQL section

DB_CONNECTION=mysql
DB_HOST=192.168.18.190 // my host machine internal ip (host.docker.internal not working)
DB_PORT=3306
DB_DATABASE=hanger
DB_USERNAME=root
DB_PASSWORD=root

Note: my DB_HOST did not work with 127.0.0.1 OR host.docker.internal so i thought it may work with my local IP, which it did.

11: To find out my local IP on MAC go to system preferences > network > My wifi connection > advanced > TCP/IP > under IPv4 192.168.43.182

The thing I’m concerned about is that my local IP keep changing, and as per the documentation The following sections will give you the IP address and/or the CNAME where the host os can be reached from within a container. https://devilbox.readthedocs.io/en/latest/advanced/connect-to-host-os.html#docker-18-03-0-ce-and-docker-compose-1-20-1 The docker should be able to connect through host.docker.internal to my Host machine, which it does not and i don’t know why. Can you please anyone please point me in the direction what should i do to figure out this issue ?

2

Answers


  1. Don’t know the exact reasoning why does it work on some mac machines and doesn’t on some, but you can force docker to map host.docker.internal by adding "host.docker.internal:host-gateway" under extra_hosts in your docker-compose. You should be able to use it post this.

    Login or Signup to reply.
  2. Same problem here, the "host.docker.internal" is for development purpose and does not work in a production environment outside of Docker Desktop.

    https://docs.docker.com/desktop/networking/#use-cases-and-workarounds-for-all-platforms

    Suggested solution:

    1. The database port (typically 3306 for mysql, mariadb, etc.) must be available on the host, you must check the firewall and open the port.

    If you use ufw, the command is the following:

    sudo ufw allow 3306
    
    1. Bind_address should be change in the database configuration.

    Access to the file can be found in general: /etc/my.cnf

    bind_address = 0.0.0.0
    

    In your case you have already do this.

    1. After that, you have to look at the IP address of the gateway of the docker bridge network and enter this value as the host access value of the database. This is usually the IP address: 172.17.0.1

    To check the bridge network details run following command:

    docker network inspect bridge
    

    Result will be a JSON where you will find the IP of bridge gateway:

    "IPAM": {
         "Driver": "default",
         "Options": null,
         "Config": [
             {
                 "Subnet": "172.17.0.0/16",
                 "Gateway": "172.17.0.1"
             }
         ]
     }
    

    If everything is set up correctly, you can access the database on the host machine from the docker container.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search