Docker Community Forums

Share and learn in the Docker community.

NodeJS Docker container can't connect to MySQL (on host)

I’m a beginner with Docker and trying it out with Ubuntu 20.04.3 LTS , Docker 20.10.8 , MySQL 8.0.26 (installed on the host).

I have a containerized nodejs trying to mysql.createPool({host: 'host.docker.internal', ...}) but I got:

Error: connect ECONNREFUSED 127.0.0.1:3306
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16)
at Protocol._enqueue (…/node_modules/mysql/lib/protocol/Protocol.js:144:48)
at Protocol.handshake (…/node_modules/mysql/lib/protocol/Protocol.js:51:23)
at PoolConection.connect (…/node_modules/mysql/lib/Connection.js:116:18)
at Pool.getConnection (…/node_modules/mysql/lib/Pool.js:48:16)

Could there be a bug in the mysql client in the node:12-alpine image? I’ve checked that docker exec -it ... ping host.docker.internal is indeed resolved as 172.17.0.1. Why is mysql.createPool({host: 'host.docker.internal', ...}) trying to look for 127.0.0.1:3306?
Despite that error, I was able to reach another container on the same host with host.docker.internal. I believe it proves that I have run --add-host=host.docker.internal:host-gateway correctly.

I’ve even built another image with 172.10.0.1 hardcoded in createPool() and run the js in a container, but to no avail.

To check that the problem didn’t stem from my js, I ran the js standalone (on the host) by node xyz.js with localhost and 127.0.0.1 supplied to createPool(), both were able to connect to MySQL. Then I did a crazy experiment by supplying 172.10.0.1 to createPool() and ran the js standalone, it gave connect ECONNREFUSED 172.17.0.1:3306
BUT if I and add 172.17.0.1 host.docker.internal to /etc/hosts(on the host) and supply host.docker.internal to createPool(), the js could connect to MySQL standalone!

What am I missing with the containerized js? Why couldn’t it reach MySQL on the host? Any idea? Thanks!

Good evening,

I use host.docker.internal on Docker for Windows to connect to the host from within a container.
To do the same on Docker for Linux I use 172.17.0.1 (with default networking) or localhost (with --net=host).
To use the same host.docker.internal on Docker on Linux with default-networking-settings you can start your container with --add-host=host.docker.internal:172.17.0.1 or use these lines in your docker-compose.yml

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

172.17.0.1 is the IP-address of the host in Docker’s default network.

Best regards
Matthias :slight_smile:

Unfortunately it gave the same result, I was using run --add-host=host.docker.internal:host-gateway, I tried your suggestion --add-host=host.docker.internal:172.17.0.1 too but to no avail.
I’m still getting

connect ECONNREFUSED 127.0.0.1:3306

Hello,
sorry for forgetting one (maybe important) thing:
by default MySQL/MariaDB installed on a host is only listening to localhost. But when you try to access from a container you are accessing it from a different IP.
So you need to configure the database-service to listen to other/all ip-addresses.
And you may need to modify your user to be allowed to access from other ip-addresses, too.

1 Like

Hello,

done a test:
have started my container (on Linux) with docker run -it --add-host=host.docker.internal:172.17.0.1 node:12-alpine ash
installed the mysql-module with npm install mysql and then created this mysqltest.js

var mysql      = require('mysql');

var pool       = mysql.createPool({
  connectionLimit : 100,
  host     : 'host.docker.internal',
  user     : 'xxxx',
  password : 'xxxx',
  database : 'xxxx',
  debug    : false,
  timezone : 'cet'
});

pool.getConnection(function(err,connection){
  if(err) {
    res.json({"code" : 100, "status" : "Error in connection database"});
    return;
  }

  console.log('connected as id ' + connection.threadId);

  try{
    sql = 'select count(*) as anz_docs from kb_docs';
    connection.query(sql, function(err, rows, fields) {
      if (!err) {
        var num_found = rows[0]['anz_docs'];
        console.log('num_found');
        console.log(num_found);
      }
    });
  }
  finally{
    connection.release();
  }
});

When running this with node mysqltest.js I got the following result:

connected as id 662
num_found
2065

which is what I expected.
Please check that the object passed to mysql.createPool contains the host only once and not multiple times with different values.

1 Like

Hi @matthiasradde thanks for the hint! I looked into my MySQL config and it’s working now.
This is what I have done:
a) under /etc/mysql/mysql.conf.d/, mysql.cnf is a blank file; mysqld.cnf had bind-address and mysqlx-bind-address both = 127.0.0.1, I changed only the bind-address to 127.0.0.1,host.docker.internal thensystemctl restart mysql
b) added an entry 172.17.0.1 host.docker.internal to /etc/hosts before
c) CREATE USER 'reader'@'%' IDENTIFIED WITH mysql_native_password BY 'xxxxx'