This question already has answers here:
ECONNREFUSED for Postgres on nodeJS with dockers
(7 answers)
Closed 5 months ago.
i'm trying to build a web app using NodeJS (with expressJS) as backend and MySQL for the database. This is all built and used with a docker-compose.yml, and a dockerfile for nodejs.
Problem is, the server can't connect to the database, it keep giving me this error in docker-compose logs :
/usr/src/app/server.js:17
if (err) throw err
^
Error: connect ECONNREFUSED 127.0.0.1:3606
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1300:16)
--------------------
at Protocol._enqueue (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:144:48)
at Protocol.handshake (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:51:23)
at PoolConnection.connect (/usr/src/app/node_modules/mysql/lib/Connection.js:116:18)
at Pool.getConnection (/usr/src/app/node_modules/mysql/lib/Pool.js:48:16)
at startServer (/usr/src/app/server.js:16:10)
at Object.<anonymous> (/usr/src/app/server.js:28:1)
at Module._compile (node:internal/modules/cjs/loader:1119:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1173:10)
at Module.load (node:internal/modules/cjs/loader:997:32)
at Module._load (node:internal/modules/cjs/loader:838:12) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 3606,
fatal: true
}
Here is my docker-compose.yml :
services:
db:
image: mysql:latest
restart: unless-stopped
environment:
- MYSQL_DATABASE = areadb
- MYSQL_ROOT_PASSWORD = password
ports:
- 3606:3606
volumes:
- sql-db:/var/lib/mysql
networks:
- backend
server:
depends_on:
- db
build: ./server
restart: unless-stopped
environment:
- MYSQL_DATABASE = areadb
- MYSQL_USER = root
- MYSQL_PASSWORD = password
- MYSQL_HOST = db
ports:
- 8080:8080
networks:
- backend
networks:
backend:
volumes:
sql-db:
And the server.js file that is used at the start :
const express = require("express");
const mysql = require("mysql");
function startServer() {
const app = express();
const port = 8080;
const pool = mysql.createPool({
connectionLimit: 10,
host: "127.0.0.1",
user: "root",
password: "password",
database: "areadb",
port: "3606"
});
pool.getConnection(function (err, connection) {
if (err) throw err
else console.log("App successfully connected to MySQL database.");
});
app.get("/", (req, res) => {
res.send("Hello World");
});
app.listen(port, function () {
console.log("Listening on port 8080");
});
}
startServer();
Please help me understand why this error happens and how can I fix it.
Notice how the correct connection information is all present in your docker-compose.yml:
environment:
- MYSQL_DATABASE = areadb
- MYSQL_USER = root
- MYSQL_PASSWORD = password
- MYSQL_HOST = db
So it would be a shame not to use it in your server.js:
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DATABASE,
port: 3606 // might also want to make this an environment variable
An an aside, instead of port 3606 I think you mean 3306, which is the default MySQL port.
Related
I developed nodeapi using docker container and when I trying to connect mysql running 'docker-compose up' throw this error.
error
my index.js
const express = require('express')
const mysql = require('mysql2');
const mysqlConfig = {
host: "cckl_mysql_server",
user: "cckl_admin",
password: "cckl_root",
database: "cckl_db",
socketPath: '/var/run/mysqld/mysqld.sock'
}
let con = null
const app = express()
app.get('/connect', function (req, res) {
con = mysql.createConnection(mysqlConfig);
con.connect(function(err) {
if (err) throw err;
res.send('connected')
});
})
docker-compose.yml
version: "3.8"
services:
cckl-app:
container_name: cckl-backend
build:
context: .
dockerfile: Dockerfile
ports:
- 8080:8080
volumes:
- .:/app
- '/app/node_modules'
depends_on:
- cckl_mysql_server
cckl_mysql_server:
image: mysql:8.0
environment:
- MYSQL_DATABASE=cckl_db
- MYSQL_USER=cckl_admin
- MYSQL_PASSWORD=cckl_root
- MYSQL_ROOT_PASSWORD=cckl_root
I am new in docker somebody hint me plz.
I am trying to get node to connect to my local mysql from within docker-compose
I have verified node connects fine from the command line, and docker compose is loading node fine - I can access functions which don't use mysql via localhost
my docker compose file
version: '3.6'
services:
mysql:
container_name: mysql
image: mysql:8.0.29
ports:
- "3306:3306"
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpw
MYSQL_USER: user
MYSQL_PASSWORD: paass
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: cine
volumes:
- './services/db/schema:/docker-entrypoint-initdb.d'
node:
container_name: node
build:
context: ./services/node
dockerfile: Dockerfile-dev
volumes:
- './services/node:/usr/src/app'
- '/usr/src/app/node_modules'
ports:
- 3001:3001
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
depends_on:
- mysql
client:
container_name: client
labels:
traefik.frontend.passHostHeader: 'true'
build:
context: ./services/client
dockerfile: Dockerfile-dev
volumes:
- './services/client:/usr/src/app'
- '/usr/src/app/node_modules'
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
- REACT_APP_API_URL=${REACT_APP_API_URL}
depends_on:
- node
nginx:
container_name: nginx
build:
context: ./services/nginx
dockerfile: Dockerfile-dev
restart: always
ports:
- 3007:80
depends_on:
- node
- client
and my node file
const app = express();
const bodyParser = require('body-parser');
const PORT = 3001;
const nodemailer = require('nodemailer');
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
require('dotenv-extended').load();
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'usser',
password : 'pass!',
database : 'cine',
port : '3306',
socketPath: '/var/run/mysqld/mysqld.sock'
});
console.log('this works');
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.get('/api', function (req, res) {
res.json({ response: "hello!" });
});
app.get('/api/listfilms', function (req, res) {
sql="select * from films;";
console.log(sql);
connection.query(sql, function (error, results, fields) {
if (error) throw error;
console.log(results);
results=JSON.parse(JSON.stringify(results))
console.log(results);
if (results == ""){
var response="error";
var resp = [{
"id": 0,
"resp": response,
},];
}else{
var resp = [{
"id": results.id,
"resp": results.name,
},];
}
res.json(resp);
})
})
the error i get is
node | Error: connect ENOENT /var/run/mysqld/mysqld.sock
node | at PipeConnectWrap.afterConnect [as oncomplete] (net.js:1107:14)
I have looked at other similar posts and tried their recommendations but none appear to work
Thanks
In your node config file the host must be mysql not localhost. Since you have network configured in between containers, you just can use myql as the host of node config file
I've created a node/mysql app and i have the following docker-compose.yaml file
version: "3.4"
x-common-variables: &common-variables
MYSQL_USER: sampleuser
MYSQL_PASSWORD: samplepassword
MYSQL_DATABASE: sampledb
services:
mysql-db:
image: mysql:5.7
container_name: mysql_container
environment:
<<: *common-variables
MYSQL_HOST: localhost
MYSQL_ROOT_PASSWORD: root
ports:
- 3308:3306
restart: always
volumes:
- ./db:/docker-entrypoint-initdb.d
phpmyadmin:
depends_on:
- mysql-db
image: phpmyadmin/phpmyadmin
container_name: phpadmin_container
environment:
PMA_HOST: mysql-db
links:
- mysql-db:mysql-db
ports:
- 8080:80
restart: always
server:
build: ./server
container_name: node_server_container
ports:
- 3000:3000
volumes:
- ./server:/app
working_dir: /app
depends_on:
- mysql-db
environment:
<<: *common-variables
MYSQL_HOST_IP: mysql-db
links:
- mysql-db
now, in the server sub directory i have a small node server
require('dotenv').config()
const express = require('express');
const setRouter = require('./routes/routes');
const port = process.env.PORT || 3000;
const app = express();
setRouter(app)
app.set('port', port);
app.use('/', (req, res) => {
return res.status(200).json({ statusCode: 200 })
});
// Listen on provided port, on all network interfaces.
app.listen(port, () => console.log(`API running on localhost:${port}`));
module.exports = app;
which connect to the mysql db:
'use strict';
const mysql = require('mysql2');
const options = {
host: process.env.MYSQL_HOST_IP,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DATABASE,
};
const pool = mysql.createPool(options);
const promisePool = pool.promise();
module.exports = promisePool;
I would like to test my endpoints, and i tried using jest and supertest but i failed miserably.
I'm trying something like this:
const app = require('../app')
const request = require('supertest');
describe('GET /users/:email', function() {
it('responds with json', async function(done) {
const res = await request(app).get('/users/Jupiter#planet.it')
expect(res.headers["Content-Type"]).toMatch(/json/);
});
});
Now, if i don't provide a .env i get a console log in my users route to print the error:
Error: Access denied for user ''#'localhost' (using password: NO)
if I provide a .env
MYSQL_HOST_IP=127.0.0.1:3306
MYSQL_USER=sampleuser
MYSQL_PASSWORD=samplepassword
MYSQL_DATABASE=sampledb
then I this error: Error: getaddrinfo ENOTFOUND 127.0.0.1:3306
How do i get to connect to the running container? (note that i run the test manually from the server folder after stopping the node container, not sure if there's a better solution)
Full repo can be found here
it has been a long day and i don't know why i am stuck at this problem for such a long time so any help is very much appreciated!
my problem is the famus code: 'ECONNREFUSED' which suddenly appeared for my project. i am trying to run a mysql db with PMA in docker and trying to connect to it from my nodejs (not in docker but on host) to get a fetch response but everything that i try and any suggestion i look at i find no solution! so any idea at this point would help me greatly and get me to bed sooner.
i cut the story short and put my codes here please do let me know with any tips, thanks in advance!
this is my server.js file
const express = require('express');
const apiroutes = require('./routes');
const app = express();
app.use(express.json());
app.use('/api/data', apiroutes);
app.listen('3000', ()=>{
console.log('server is running on port: 3000');
});
this is my routes file
const express = require('express');
const db = require('../db');
const router = express.Router();
router.get('/', async(req, res, next)=>{
try{
let results = await db.all();
res.json(results);
} catch(error){
console.log(error);
res.sendStatus(500);
}
});
module.exports = router;
this is my db file
const mysql = require('mysql');
const pool = mysql.createPool({
connectionLimit : 100,
password: 'secret',
user: 'user',
database: 'db_test',
host: 'localhost',
port: '3306'
});
let wholeDB = {};
wholeDB.all = () => {
return new Promise((resolve, reject)=>{
pool.query(`SELECT * FROM table1`,(error, result)=>{
if(error){
return reject(error);
}
return resolve(result);
});
});
};
module.exports = wholeDB;
this is my dockerfile
FROM php:7.2-fpm-alpine
RUN docker-php-ext-install pdo pdo_mysql
and finaly this is my docker-compose file
version: '3'
networks:
vuePhP:
services:
nginx:
image: nginx:stable-alpine
container_name: nginxWebServer
ports:
- "8088:80"
volumes:
- ./src:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- mysql
- php
networks:
- vuePhP
mysql:
image: mysql
container_name: mysqlService
restart: unless-stopped
tty: true
ports:
- "4306:3306"
volumes:
- ./mysql:/var/lib/mysql
environment:
MYSQL_DATABASE: db_test
MYSQL_USER: user
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: root
networks:
- vuePhP
phpmyadmin:
image: phpmyadmin
container_name: phpMyAdmin
restart: always
depends_on:
- mysql
- php
environment:
- PMA_HOST=mysql
- PMA_PORT=3306
ports:
- "8081:80"
networks:
- vuePhP
php:
build:
context: .
dockerfile: Dockerfile
container_name: phpService
volumes:
- ./src:/var/www/html
ports:
- "9000:9000"
networks:
- vuePhP
and this is the error that i get when i use postman to do a get command
errno: -111, code: 'ECONNREFUSED', syscall: 'connect',
address: '127.0.0.1', port: 3306, fatal: true
Error: connect ECONNREFUSED 127.0.0.1:3306
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1157:16)
thank you!
edit: i have added the port 4306 to the node app and get this error :
code: 'ER_NOT_SUPPORTED_AUTH_MODE', errno: 1251, sqlMessage:
'Client does not support authentication protocol requested by server;
consider upgrading MySQL client', sqlState: '08004', fatal: true
i added this line in my compose file but it didn't help:
mysql:
image: mysql
container_name: mysqlService
restart: unless-stopped
tty: true
ports:
- "4306:3306"
volumes:
- ./mysql:/var/lib/mysql
environment:
MYSQL_DATABASE: KFV_test
MYSQL_USER: user
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: root
command: --default-authentication-plugin=mysql_native_password
networks:
- vuePhP
ah i found it, the problem is the version of mysql in composer and usage of mysql library instead of mysql2 as Phil graciously mentioned. so i downgraded mysql version by version until i found the one that worked and before that added mysql2 (npm i mysql2) to my nodejs app. and it worked. here my is my changes in docker-compose file. btw changed the ports as well not that it helped before the downgrade.
mysql:
image: mysql:5.7.24
container_name: mysqlService
restart: unless-stopped
tty: true
ports:
- "3306:3306"
volumes:
- ./mysql:/var/lib/mysql
environment:
MYSQL_DATABASE: db_test
MYSQL_USER: user
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: root
networks:
- vuePhP
and changed the connection method in my db file:
const mysql2 = require('mysql2');
const connection = mysql2.createConnection({
host: 'localhost',
user: 'user',
password: 'secret',
database: 'db_test',
});
let wholeDB = {};
wholeDB.all = () => {
return new Promise((resolve, reject)=>{
connection.query(`SELECT * FROM table1`,(error, result)=>{
if(error){
return reject(error);
}
return resolve(result);
});
});
};
module.exports = wholeDB;
var mysql = require('mysql')
var connection = mysql.createPool({
host: "localhost",
user: "root",
password: "",
database: "dbName",
port : "3306"
})
connection.getConnection((err, connection) => {
if (err) {
if (err.code === 'PROTOCOL_CONNECTION_LOST') {
console.error('Database connection was closed.')
}
if (err.code === 'ER_CON_COUNT_ERROR') {
console.error('Database has too many connections.')
}
if (err.code === 'ECONNREFUSED') {
console.error('Database connection was refused.')
}
}
if (connection) connection.release()
return
})
module.exports = connection
example :
import connection from '../Modules/connection.js';
let LoginQuery = (values) => {
return new Promise((resolve, reject) => {
// let sql = `SELECT * FROM user_tbl WHERE mobile_number ="${values.mobile_number}" OR email_id="${values.mobile_number}"`;
let sql = "SELECT * FROM `admin_tbl` WHERE mobile_number = ? OR email_id = ?";
connection.query(sql, Object.values(values), (err, result) => {
console.log(err);
err ? reject(err) : resolve(result);
});
});
};
Please use this connecting pool hope it'll work.
Attempting to connect database from within the microservice, failing to the connect the database
Error: connect ECONNREFUSED 172.18.0.2:3306
service/index.js
var http = require('http');
//create a server object:
http.createServer(function (req, res) {
res.write('Hello World!'); //write a response to the client
res.end(); //end the response
}).listen(8080); //the server object listens on port 8080
console.log("Listening at 8080");
var mysql = require('mysql');
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
});
con.connect(function(err) {
if (err) throw err;
console.log("Database Connected!");
});
docker-compose.yml
version: '3'
services:
database:
build:
./database
ports:
- "6603:3306"
image: "test-mysql"
container_name: "test-mysql"
service:
build:
./service
ports:
- "8080:8080"
depends_on:
- database
image: "test-nodejs"
container_name: "test-nodejs"
restart: on-failure
I've attempted connecting to database with different settings.
1) Without port
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
});
2) specified port 3306
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
port: 3306
});
3) specified port 6603
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password",
port: 6603
});
database/Dockerfile
FROM mysql
ENV MYSQL_DATABASE=test
ENV MYSQL_ROOT_PASSWORD=password
EXPOSE 6603:3306
COPY ./schema.sql /docker-entrypoint-initdb.d/
Basically how my node.js microservice can discover the database service?
Edit
I suspected that database wasn't ready by the time nodejs kicks in, so I added some delay before connecting to database and error changed
Updated Code
setTimeout(function(){
var mysql = require('mysql');
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
});
con.connect(function(err) {
if (err) throw err;
console.log("Database Connected!");
});
}, 20 * 1000);
output
Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
Probably you are using a version of MySQL that doesnt support the login you are trying. Try with mysql v5.7:
docker run -d -p 6603:3306 --name mysql-container -e MYSQL_ROOT_PASSWORD=password mysql:5.7
You miss order:
First connect to database, then listen the port.
var http = require('http');
var mysql = require('mysql');
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
} );
con.connect(function(err) {
if (err) throw err;
console.log("Database Connected!");
});
//create a server object:
http.createServer(function (req, res) {
res.write('Hello World!'); //write a response to the client
res.end(); //end the response
}).listen(8080); //the server object listens on port 8080
console.log("Listening at 8080");
the database port does not get translated as it's within the container. just use 3306 in your app