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

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.

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

Related

trying to connect typeorm to mysql container in docker-compose but got this error Error: Access denied for user ''#'172.29.0.3' (using password: YES)

I am running node and mysql containers with docker compose and try to connect typeorm with mysql container but I got the same error over and over
this my docker-compose file
version: '3.8'
services:
db:
image: mysql
restart: always
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: password
app:
build: .
command: npm start
volumes:
- .:/usr/app/
ports:
- '8000:8000'
depends_on:
- db
environment:
MYSQL_HOST: db
MYSQL_NAME: test
MYSQL_PASSWORD: password
this is my typeorm config file
import {DataSource} from 'typeorm';
import * as dotenv from 'dotenv';
dotenv.config();
export const appDataSource = new DataSource({
type: 'mysql',
host: process.env.MYSQL_HOST,
port: 3306,
password: process.env.MYSQL_PASSWORD,
entities:[
'src/entities/*.js'
],
synchronize: true,
logging: true
});
and this is my .env file
MYSQL_USER = root
MYSQL_PASSWORD = password
MYSQL_NAME = test
MYSQL_HOST = db
MYSQL_PASSWORD = password
Your MySQL and application container seems to be in two different networks.
Try with following docker-compose :
version: '3.8'
services:
db:
image: mysql
restart: always
network_mode: "host"
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: password
app:
build: .
command: npm start
network_mode: "host"
volumes:
- .:/usr/app/
ports:
- '8000:8000'
depends_on:
- db
environment:
MYSQL_HOST: db
MYSQL_NAME: test
MYSQL_PASSWORD: password
here both containers will run on host.
For fixing : > Error: getaddrinfo EAI_AGAIN
Try adding following to /etc/hosts file. (If you are on Linux destro)
0.0.0.0 db
0.0.0.0 app

Error database connect is not a function Nodejs with Mysql in docker

I have deployed my docker application (to DigitalOcean). Everything work's, but I can't connect mysql with nodejs.
When I run docker-compose up I get error database.connect is not a function.
My server.js file is look like this
const mysql = require("mysql");
const database = mysql.createPool({
host: process.env.MYSQL_HOST_IP,
user: "db_user",
password: "db_user_pass",
database: "guess-game",
port: 3306,
});
database.connect((err) => {
if (err) {
console.error("error connecting: " + err.stack);
return;
}
console.log("connected as id " + db.threadId);
});
module.exports = db;
I don't know what I need to write this line to make it work.
host: process.env.MYSQL_HOST_IP,
I tried to add droplet IP as host, but this is also don't work.
host: "http://46.101.162.111/",
Also, I try this.
host: "46.101.162.111",
My docker-compose.yml file
version: "3"
networks:
dbnet:
services:
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin1
environment:
- PMA_ARBITRARY=1
- PMA_HOST=db
restart: always
links:
- db
ports:
- 8899:80
depends_on:
- db
networks:
- dbnet
api:
build: ./api
container_name: api1
command: npm run start
restart: unless-stopped
ports:
- "3005:3005"
environment:
- PORT=3005
- MYSQL_HOST_IP=172.18.0.2
depends_on:
- phpmyadmin
networks:
- dbnet
db:
image: mysql:latest
container_name: db
command: --default-authentication-plugin=mysql_native_password
environment:
- MYSQL_ROOT_PASSWORD=my_secret_password
- MYSQL_DATABASE=guess-game
- MYSQL_USER=db_user
- MYSQL_PASSWORD=db_user_pass
restart: always
ports:
- 6033:3306
networks:
- dbnet
Struggling almost 3 days. 😣
You just need to indicate a DB container name instead of IP like this:
MYSQL_HOST_IP=db

Node.js able to connect to MySQL container when app is ran locally but unable to connect when app is ran in a container

Docker-Compose file:
version: '3.8'
networks:
app-tier:
driver: bridge
services:
mysql_node:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: 'sample_db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- '3306:3306'
expose:
- '3306'
volumes:
- mysql_db:/var/lib/mysql
app:
depends_on:
- mysql_node
build: .
ports:
- 3000:3000
environment:
- MYSQL_HOST=mysql_node
- MYSQL_USER=root
- MYSQL_PASSWORD=password
- MYSQL_NAME=sample_db
- MYSQL_PORT=3306
- MYSQL_HOST_IP=mysql_node
networks:
- app-tier
volumes:
- .:/app
volumes:
mysql_db:
docker file:
FROM node:latest
RUN mkdir app
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "app.js"]
Sourcecode:
const http = require('http')
var mysql = require('mysql');
const hostname = '0.0.0.0'
const port = 3000
console.log(process.env.MYSQL_HOST_IP)
console.log(process.env.MYSQL_PORT)
var con = mysql.createConnection({
host: "process.env.MYSQL_HOST_IP",
user: "user",
password: "password",
port: 3306
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
When I run docker-compose up the MySQL container successfully launches. But the app exits, with error code Error: connect ETIMEDOUT.
When I run the app locally via node app.js I end up getting a successful "Connected!" message output to my console.
I'm able to connect to the database via MySQLWorkbench as well. It's just the app is unable to connect to the db when the app is ran as a container.
You've specified that the app should be on a named network and the database shouldn't. Then the database service goes on the default network and the two containers can't talk to each other.
I'd remove the named network from the app, since it's probably not needed.
app:
depends_on:
- mysql_node
build: .
ports:
- 3000:3000
environment:
- MYSQL_HOST=mysql_node
- MYSQL_USER=root
- MYSQL_PASSWORD=password
- MYSQL_NAME=sample_db
- MYSQL_PORT=3306
- MYSQL_HOST_IP=mysql_node
volumes:
- .:/app

Connect JavaScript running in docker container to MySQL database running on another docker container

I'm currently running a local instance of RocketChat and the RocketBot using docker-compose and a corresponding docker-compose.yaml file:
I use the standard mysql module like this:
var con = mysql.createConnection({
host: '<placeholder>',
user: 'root',
port: '3306',
password: '<placeholder>',
});
The host, user, port and password are gathered from running the inspect command on the container containing the MySQL server. The MySQL does work as I can run it and make changes to it and even connect to it using MySQL workbench. I get this error:
rosbot_1 | [Tue Jun 18 2019 18:42:06 GMT+0000 (UTC)] ERROR Error: connect ETIMEDOUT
rosbot_1 | at Connection._handleConnectTimeout (/home/hubot/node_modules/mysql/lib/Connection.js:412:13)
I have no idea how to proceed now, how can I connect from the bot served by docker-compose to the MySQL container using JavaScript?
EDIT:
docker-compose.yaml:
version: '2.1'
services:
mongo:
image: mongo:3.2
hostname: 'mongo'
volumes:
- ./db/data:/data/db
- ./db/dump:/dump
command: mongod --smallfiles --oplogSize 128 --replSet rs0
mongo-init-replica:
image: mongo:3.2
command: 'mongo mongo/rocketchat --eval "rs.initiate({ _id: ''rs0'', members: [ { _id: 0, host: ''localhost:27017'' } ]})"'
links:
- mongo:mongo
rocketchat:
image: rocketchat/rocket.chat:latest
hostname: 'rocketchat'
volumes:
- ./rocketchat/uploads:/app/uploads
environment:
- PORT=3000
- ROOT_URL=http://localhost:3000
- MONGO_URL=<placeholder>
- MONGO_OPLOG_URL=<placeholder>
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000"]
interval: 30s
timeout: 10s
retries: 5
links:
- mongo:mongo
ports:
- 3000:3000
<placeholder>:
image: <placeholder>
hostname: "<placeholder>"
environment:
- ROCKETCHAT_URL=<placeholder>
- ROCKETCHAT_ROOM=""
- ROCKETCHAT_USER=<placeholder>
- ROCKETCHAT_PASSWORD=<placeholder>
- ROCKETCHAT_AUTH=<placeholder>
- BOT_NAME=<placeholder>
- LISTEN_ON_ALL_PUBLIC=true
- EXTERNAL_SCRIPTS=hubot-help,hubot-seen,hubot-links,hubot-diagnostics,hubot-pugme,hubot-reload
- PENTEXT_PATH=/home/hubot/pentext
- ADDITIONAL_PACKAGES=mysql,lodash
- RESPOND_TO_LIVECHAT=true
- RESPOND_TO_DM=true
depends_on:
rocketchat:
condition: service_healthy
links:
- rocketchat:rocketchat
volumes:
- <placeholder>
ports:
- 3001:3001
Normally, you can connect to another container using the container name as hostname:
If you have a container with mysql, the container name (in this example 'db') is the host name to access the mysql container (also, you can use a hostname: 'mysqlhostname' to specify a different name):
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: mypass
MYSQL_DATABASE: mydb
In your rocketchat container you should add some environment variables for mysq root password and database to make it available to your container
rocketchat:
image: rocketchat/rocket.chat:latest
hostname: 'rocketchat'
volumes:
- ./rocketchat/uploads:/app/uploads
environment:
- PORT=3000
- ROOT_URL=http://localhost:3000
- MONGO_URL=<placeholder>
- MONGO_OPLOG_URL=<placeholder>
- MYSQL_ROOT_PASSWORD: mypass
- MYSQL_DATABASE: mydb
- MYSQL_HOSTNAME: db
...
links:
- rocketchat:rocketchat
- db : db
And then, use the host name and the environment variables to create your connection:
var con = mysql.createConnection({
host: 'db', // or process.env.MYSQL_HOSTNAME
user: 'root',
port: '3306',
password: 'mypass', // or process.env.MYSQL_ROOT_PASSWORD
});

TCPConnectWrap.afterConnect - node can't get data from mysql when are in docker compose

I'm trying to connect node with mysql through dokcer-compose. I can access mysql with workbench but when I try to connect with node I get the error:
Error: connect ECONNREFUSED 127.0.0.1:3306
     at TCPConnectWrap.afterConnect [as oncomplete] (net.js: 1054: 14))
Does anyone know what is going on?
docker-compose.yml
version: '3'
services:
#App Service
app:
image: "node:alpine"
container_name: cms-node
restart: unless-stopped
tty: true
working_dir: /app
environment:
- NODE_ENV=production
ports:
- 1234:1234
volumes:
- ./:/app
links:
- db
depends_on:
- db
#Mysql Service
db:
image: mysql:latest
container_name: cms-mysql
restart: unless-stopped
# command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: CMS
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
ports:
- 3306:3306
node create connection
const db: Connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'CMS',
});
export default db;
node try to connect
db.connect((err) => {
if (err) {
throw err;
}
console.log('Connected!');
});
You should use the link name (by default, the name of the linked service) as the hostname to connect to. See the docker-compose.yml documentation for details.
So just use host: 'db' instead of host: 'localhost'
Yes, we have to use service name from docker-compose.yml. I faced a similar issue when there was a custom front end API Gateway server (working as proxy) written in node.js connecting to other two services. So replacing localhost:3001 with serviceName:30001 fixed the issue.
Example code:
...
const proxy = require('express-http-proxy');
...
app.use('/json-parser', proxy('json_parsing_api:3001'));
app.get('/json-parser/json-to-person', proxy('json-to-person'));