Home  >  Q&A  >  body text

Node.js connect to MySQL Docker container ECONNREFUSED

Before marking this question as a duplicate, please note that I did read the other answer and it did not solve my problem.

I have a Docker compose file containing two services:

version: "3"
services:
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_HOST: localhost
      MYSQL_DATABASE: mydb
      MYSQL_USER: mysql
      MYSQL_PASSWORD: 1234
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3307:3306"
    expose:
      - 3307
    volumes:
      - /var/lib/mysql
      - ./mysql/migrations:/docker-entrypoint-initdb.d
    restart: unless-stopped
  web:
    build:
      context: .
      dockerfile: web/Dockerfile
    volumes:
      - ./:/web
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: development
      PORT: 3000
    links:
      - mysql:mysql
    depends_on:
      - mysql
    expose:
      - 3000
    command: ["./wait-for-it.sh", "mysql:3307"]

/web/Dockerfile:

FROM node:6.11.1

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY package.json /usr/src/app/
RUN npm install

COPY . /usr/src/app

CMD [ "npm", "start" ]

After docker-compose up --build, the service starts, but the "wait-for-it.sh" script times out while waiting for mySQL to start (so don't use it temporarily when testing the DB) connection, I just wait until the console shows MySQL is ready to accept incoming connections)

When MySQL is running from the host, I can use Sequel Pro to log in and query the database and get sample records from ./mysql/migrations


I can also SSH into the running MySQL container and perform the same operation.

However, my Node.js application generates ECONNREFUSED 127.0.0.1:3307

when connecting

MySQL initialization:

import * as mysql from 'promise-mysql'

const config = {
    host: 'localhost',
    database: 'mydb',
    port: '3307',
    user: 'mysql',
    password: '1234',
    connectionLimit: 10
}

export let db = mysql.createPool(config);

MySQL query:

import { db } from '../db/client'

export let get = () => {

return db.query('SELECT * FROM users', [])
    .then((results) => {
        return results

    })
    .catch((e) => {
        return Promise.reject(e)
    })
}

The route called when the url is clicked /

import { Router } from 'express';
import * as repository from '../repository'
export let router = Router();

router.get('/', async (req, res) => {

    let users;

    try{
        users = await repository.users.get();
    } catch(e){
        // ECONNREFUSED 127.0.0.1:3307
    }

    res.render('index', {
        users: users
    });
});

This is unlikely to be a race condition because at the same time that Node.js fails, I can query the running Docker container using Sequel Pro or SSH and query it. So this could be a case of Node.js not being able to access the MySQL container?

{
    error: connect ECONNREFUSED 127.0.0.1:3307
    code: 'ECONNREFUSED',
    errno: 'ECONNREFUSED',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 3307,
    fatal: true
}


P粉296080076P粉296080076271 days ago602

reply all(1)I'll reply

  • P粉399090746

    P粉3990907462024-01-22 12:20:58

    this:

    mysql:
        image: mysql:5.7
        environment:
        ...
        ports:
          - "3307:3306"

    means that Docker will map the host's 3307 port to the container's 3306 port. So you can access localhost:3307 from Sequel.

    However, this does not mean that the container is listening to 3307; in fact, the container is still listening to 3306. When other containers try to access the mysql DNS, it is translated to the internal container IP, so you must connect to 3306.

    So your node configuration should look like this:

    const config = {
        host: 'mysql',
        database: 'mydb',
        port: '3306',
        user: 'mysql',
        password: '1234',
        connectionLimit: 10
    }

    This is in your docker-compose.yml:

    command: ["./wait-for-it.sh", "mysql:3306"]

    Note: wait-for-it.sh Script from: https://github.com/vishnubob/wait-for-it

    reply
    0
  • Cancelreply