Docker Compose getting error ECONNREFUSED 127.0.0.1:3306 with MySQL and NodeJS

13,906

I think your db is taking more time to start and your app is starting before the db, try something like this for your docker-compose.yml file:

version: "3.8"

networks:
  app-tier:
    driver: bridge

services:
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    expose:
      - "3306"
    ports:
      - "3306:3306"    
    networks:
      - app-tier      
    environment:
      MYSQL_DATABASE: school
      MYSQL_ALLOW_EMPTY_PASSWORD: ok
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: dbuser
      MYSQL_PASSWORD: dbuser
      MYSQL_ROOT_HOST: '%'
  backend:
    depends_on:
      - db
    build: .
    command: bash -c 'while !</dev/tcp/db/3306; do sleep 1; done; npm start'
    ports:
      - "3000:3000"
    networks:
      - app-tier   
Share:
13,906
Carlos Isidoro López
Author by

Carlos Isidoro López

Updated on June 05, 2022

Comments

  • Carlos Isidoro López
    Carlos Isidoro López almost 2 years

    I am trying to setup some containers for my NestJS + TypeORM + MySQL environment by using Docker Compose in a Windows 10 host, but I am getting an ECONNREFUSED error:

    connect ECONNREFUSED 127.0.0.1:3306 +2ms
    backend_1  | Error: connect ECONNREFUSED 127.0.0.1:3306
    backend_1  |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1145:16)
    backend_1  |     --------------------
    backend_1  |     at Protocol._enqueue (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:144:48)
    backend_1  |     at Protocol.handshake (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:51:23)        
    backend_1  |     at PoolConnection.connect (/usr/src/app/node_modules/mysql/lib/Connection.js:116:18)
    backend_1  |     at Pool.getConnection (/usr/src/app/node_modules/mysql/lib/Pool.js:48:16)
    backend_1  |     at /usr/src/app/node_modules/typeorm/driver/mysql/MysqlDriver.js:793:18
    backend_1  |     at new Promise (<anonymous>)
    backend_1  |     at MysqlDriver.createPool (/usr/src/app/node_modules/typeorm/driver/mysql/MysqlDriver.js:790:16)
    backend_1  |     at MysqlDriver.<anonymous> (/usr/src/app/node_modules/typeorm/driver/mysql/MysqlDriver.js:278:51)
    backend_1  |     at step (/usr/src/app/node_modules/typeorm/node_modules/tslib/tslib.js:141:27)
    backend_1  |     at Object.next (/usr/src/app/node_modules/typeorm/node_modules/tslib/tslib.js:122:57)
    

    I have created the following Dockerfile to configure the NestJS API container:

    FROM node:12-alpine
    WORKDIR /usr/src/app
    
    COPY package.json .
    RUN npm install
    
    EXPOSE 3000
    
    #CMD ["npm", "start"]
    
    CMD /wait-for-it.sh db:3306 -- npm start
    
    COPY . .
    

    And then I reference this from Docker Compose with the following docker-compose.yml:

    version: "3.8"
    
    networks:
      app-tier:
        driver: bridge
    
    services:
      db:
        image: mysql
        command: --default-authentication-plugin=mysql_native_password
        restart: always
        expose:
          - "3306"
        ports:
          - "3306:3306"    
        networks:
          - app-tier      
        environment:
          MYSQL_DATABASE: school
          MYSQL_ALLOW_EMPTY_PASSWORD: ok
          MYSQL_ROOT_PASSWORD: root
          MYSQL_USER: dbuser
          MYSQL_PASSWORD: dbuser
          MYSQL_ROOT_HOST: '%'
      backend:
        depends_on:
          - db
        build: .
        ports:
          - "3000:3000"
        networks:
          - app-tier      
    

    Finally, I set the TypeORM configuration to match with the Docker Compose file:

    export const DB_CONFIG: TypeOrmModuleOptions = {
        type: 'mysql',
        host: 'db',
        port: 3306,
        username: 'dbuser',
        password: 'dbuser',
        database: 'school',
        entities: [], // We specify the entities in the App Module.
        synchronize: true,
    };
    

    I am kind of new to Docker Compose, but I have tried many things like changing the output port to 3307, setting an explicit network... and the port 3306 is free in my host OS when I run it. Any help?

    Edit 1

    I have included MYSQL_ROOT_HOST and wait-for-it.sh as suggested, but still no results.

  • Carlos Isidoro López
    Carlos Isidoro López over 3 years
    Thank you, it worked. I just had to add RUN apk update && apk add bash in my Dockerfile so it can execute bash.
  • rickster
    rickster about 2 years
    where did you added the this command in Dockerfile ?