0

I have been having troubles reaching mysql server from my dockarized nodejs app. I can access the database normally with localhost, port 3307, password, user and database in workbenceh so I assumed I can just do the same in my nodejs app but with 3306.

No matter what configuration I have tried I've always gotten the -111, ECONNREFUSED, connect... error back.

Mysql server is ready for connections before nodejs starts and is listening on 3306. I have the right users with the right privelages... I really don't know what I am missing at this point.

version: '3.3'
services:
  db:
    image: mysql:8
    restart: always
    volumes:
      - db:/var/lib/mysql
    env_file: ./.env
    environment:
        MYSQL_ROOT_PASSWORD: password
        MYSQL_DATABASE: database
        MYSQL_ROOT_USER: user
    ports:
      - 3307:3306
  app:
    container_name: app_con
    build: ./
    restart: always
    env_file: ./.env
    ports:
      - 5000:5000
    stdin_open: true
    tty: true
    depends_on:
      - db
volumes: 
  db:

My node.js connection:

const pool = mysql.createPool({
    connectionLimit: 15,
    host: localhost, /*I have tried 127.0.0.1, 0.0.0.0, 172..., my lan ip*/
    user: user,
    password: password,
    port: 3306, /*I have also tried 3307*/
    database: database,
    multipleStatements: true
});
Janez Kranjski
  • 115
  • 2
  • 10
  • 2
    so you are trying to connect from a nodejs app in the `app` container to a mysql database in the `db` container, right? Then you must not use localhost, because `localhost` (or 127.0.0.1) is that very same container it self. You have to use the ipaddress (or networkname) of the database container. – derpirscher Jan 30 '22 at 10:47
  • @derpirscher I have also tried setting `environment: SQL_HOST: db` and then connecting to that IP(172.20.0.2) but I assumed it was incorrect because I got this error: `Client does not support authentication protocol requested by server; consider upgrading MySQL client`. I will try to troubleshoot this and see if it connects. – Janez Kranjski Jan 30 '22 at 11:01
  • Well, that did actually connect to the server, but there seems to be some incompatibility between your server and your client. See for instance this error on how to address that problem https://stackoverflow.com/questions/50093144/mysql-8-0-client-does-not-support-authentication-protocol-requested-by-server – derpirscher Jan 30 '22 at 12:05

1 Answers1

0

I am going to try this once.

  1. A container is actually just a process, BUT it acts like a vm. It has its own hostname and IP address. This means "localhost" inside one container refers to that container. Not the host, not the other container.

  2. As they have their own IPs, containers connect to each other over virtual networks using those IPs. When they connect like this, they can connect to ANY port being listened on by services in the other. They use each others IP address, or service name to connect over these virtual networks. container to container networking does NOT use "EXPOSE", "PUBLISH", "Ports", "-" etc. directives and there is no port remapping. If software listens on port :80, then connecting software must connect on port :80

  3. The "ports:" directive, or "-p" on the docker run command is used to publish a port from a container to the host. This bridges a port from the container, to the host. "-p 1234:5678" This will make port 1234 on the host bridge through, and communicate with 5678 in the container. "Ports" "Publish" and "Expose" are purely used for container to host networking.

Putting this together: When "app" tries to conenct to "db", it must use "db:3306" for the connection. Regardless of what Ports might say, or if there is a Ports directive at all. If the service name is "mysqldb" then the connection string must be "mysqldb:3306".

If you are trying to connect to the db from your desktop, then you must use the port from the lhs of the ports directive, plus localhost, because thats the bridged end of the port. i.e. "3307:3306" means that "locolhost:3307" would be used from a desktop tool to reach into docker to reach the mysql container, and connect to it on its :3306 port.

The rhs of the ports directive for "app" must be whatever the nodejs app is actually listening on. If the nodejs app listens on :5000, then the rhs must be 5000. If there is a message about the port being unavialable, then its unavailable inside the container, and the app needs to be configured to listen on a different port, and the ports directive needs to change to reflect that. The lhs port can be any port that is not used on the host, that is easy and convenient to use in your browser. E.g. "8080". Setting app's Ports directive to - 8080:5000 would let you enter http://localhost:8080 in your desktop browser to access the app. Just make sure the nodejs app is listening on :5000.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148