Docker - SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306

I'm trying to get my nodejs application up and running using a docker container. I have no clue what might be wrong. The credentials seems to be passed correctly when I debug the credentials with the console. Also firing up sequel pro and connecting directly with the same username and password seems to work. When node starts in the container I get the error message:

SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306

The application itself is loading correctly on port 3000, however no data is retrieved from the database. If have also tried adding the environment variables directly to the docker compose file, but this also doesn't seem to work.

My project code is hosted over here: https://github.com/pietheinstrengholt/rssmonster

The following database.js configuration is used. When I add console.log(config) the correct credentials from the .env file are displayed.

require('dotenv').load();

const Sequelize = require('sequelize');
const fs = require('fs');
const path = require('path');
const env = process.env.NODE_ENV || 'development';
const config = require(path.join(__dirname + '/../config/config.js'))[env];

if (config.use_env_variable) {
  var sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  var sequelize = new Sequelize(config.database, config.username, config.password, config);
}

module.exports = sequelize;

When I do a console.log(config) inside the database.js I get the following output:

{
username: 'rssmonster',
password: 'password',
database: 'rssmonster',
host: 'localhost',
dialect: 'mysql'
}

Following .env:

DB_HOSTNAME=localhost
DB_PORT=3306
DB_DATABASE=rssmonster
DB_USERNAME=rssmonster
DB_PASSWORD=password

And the following docker-compose.yml:

version: '2.3'
services:

  app:
    depends_on:
      mysql:
        condition: service_healthy
    build:
      context: ./
      dockerfile: app.dockerfile
    image: rssmonster/app
    ports:
      - 3000:3000
    environment:
      NODE_ENV: development
      PORT: 3000
      DB_USERNAME: rssmonster
      DB_PASSWORD: password
      DB_DATABASE: rssmonster
      DB_HOSTNAME: localhost
    working_dir: /usr/local/rssmonster/server
    env_file:
      - ./server/.env
    links:
      - mysql:mysql

  mysql:
    container_name: mysqldb
    image: mysql:5.7
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: "yes"
      MYSQL_DATABASE: "rssmonster"
      MYSQL_USER: "rssmonster"
      MYSQL_PASSWORD: "password"
    ports:
      - "3307:3306"
    volumes:
      - /var/lib/mysql
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
      timeout: 5s
      retries: 10

volumes:
  dbdata:

Error output:

{ SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306
app_1    |     at Promise.tap.then.catch.err (/usr/local/rssmonster/server/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:128:19)
app_1    | From previous event:
app_1    |     at ConnectionManager.connect (/usr/local/rssmonster/server/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:125:13)
app_1    |     at sequelize.runHooks.then (/usr/local/rssmonster/server/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:306:50)
app_1    | From previous event:
app_1    |     at ConnectionManager._connect (/usr/local/rssmonster/server/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:306:8)
app_1    |     at ConnectionManager.getConnection (/usr/local/rssmonster/server/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:247:46)
app_1    |     at Promise.try (/usr/local/rssmonster/server/node_modules/sequelize/lib/sequelize.js:564:34)
app_1    | From previous event:
app_1    |     at Promise.resolve.retryParameters (/usr/local/rssmonster/server/node_modules/sequelize/lib/sequelize.js:464:64)
app_1    |     at /usr/local/rssmonster/server/node_modules/retry-as-promised/index.js:60:21
app_1    |     at new Promise (<anonymous>)

Solution 1:

Insteaf of localhost point to mysql which is the service name (DNS) that nodejs will resolve into the MySQL container:

DB_HOSTNAME: mysql

And

 {
  ...
  host: 'mysql',
  ...
 }

Solution 2:

Inside of the container you should reference the container by the name you gave in your docker-compose.yml file.

In this case you should use

DB_HOSTNAME: mysql