Can't connect to mongo in Docker - node.js

I'm practicing Docker with a dummy app but I can't connect with the database. If anyone can give a clue about what the problem could be, please. Thanks in advance for any help. If any more info is needed please let me know.
Here is my Dockerfile for api:
Dockerfile in server
FROM node:14-alpine
WORKDIR usr/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3400
CMD ["npm", "start"]
Here is my connection to db in db.js
const mongoose = require('mongoose');
const uri = 'mongodb://mongo:27017/prueba-docker';
const connect = async () => {
try {
await mongoose.connect(uri, {});
console.log('conected to db');
} catch (err) {
console.log('error connecting to db', err);
}
};
module.exports = { connect };
And here docker-compose
version: "3"
services:
prueba-react:
image: prueba-react
build: ./client/
stdin_open: true
ports:
- "3000:3000"
networks:
- mern-app
prueba-api:
image: prueba-api
build: ./server/
ports:
- "3400:3400"
networks:
- mern-app
depends_on:
- db
db:
image: mongo:4.4-bionic
ports:
- "27017:27017"
networks:
- mern-app
volumes:
- mongo-data:/data/db
networks:
mern-app:
driver: bridge
volumes:
mongo-data:
driver: local
First I found out that I should stop mongo wiht the command because I had a port conflict.
sudo systemctl stop mongod
But now I don't understand why It gives an error when I do docker-compose up
This is the error I get
prueba-api_1 | error connecting to db MongooseServerSelectionError: getaddrinfo EAI_AGAIN mongo
prueba-api_1 | at NativeConnection.Connection.openUri (/usr/app/node_modules/mongoose/lib/connection.js:796:32)
prueba-api_1 | at /usr/app/node_modules/mongoose/lib/index.js:328:10
prueba-api_1 | at /usr/app/node_modules/mongoose/lib/helpers/promiseOrCallback.js:32:5
prueba-api_1 | at new Promise (<anonymous>)
prueba-api_1 | at promiseOrCallback (/usr/app/node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:10)
prueba-api_1 | at Mongoose._promiseOrCallback (/usr/app/node_modules/mongoose/lib/index.js:1149:10)
prueba-api_1 | at Mongoose.connect (/usr/app/node_modules/mongoose/lib/index.js:327:20)
prueba-api_1 | at Object.connect (/usr/app/db.js:6:20)
prueba-api_1 | at Object.<anonymous> (/usr/app/app.js:6:4)
prueba-api_1 | at Module._compile (internal/modules/cjs/loader.js:1072:14) {
prueba-api_1 | reason: TopologyDescription {
prueba-api_1 | type: 'Unknown',
prueba-api_1 | servers: Map(1) { 'mongo:27017' => [ServerDescription] },
prueba-api_1 | stale: false,
prueba-api_1 | compatible: true,
prueba-api_1 | heartbeatFrequencyMS: 10000,
prueba-api_1 | localThresholdMS: 15,
prueba-api_1 | logicalSessionTimeoutMinutes: undefined
prueba-api_1 | }

In your docker-compose.yml you are creating a network called mern-app where all services are assigned to that network. To communicate between containers in a docker network all you have to do is use the service name. Instead of mongodb://mongo:27017/prueba-docker try connecting to mongodb://db:27017/prueba-docker.
You also mentioned a port conflict. It seems like you are already running mongodb. If you don't want to stop your mongodb everytime you want to try out your docker-compose, you could just map to another port:
ports:
- "27018:27017"
Or you could just don't expose your mongodb at all if no external application is using your db. This only introduces security threats.

Related

Docker with Knex and PG: cannot run migration or get data from database but can connect via GUI only

I'm building a project with Node, Knex, PostgreSQL and I'm Dockerizing my project.
The main issue I have I'm unable to run the migration and also to get the data from the DB using Knex.
What I can do is use DB GUI such as Tableplus to connect to the DB.
You can find my project here:
Repo of the project
All I read online is not working for me as
use the service name \ container name -> not working :(
use full postgres url as postgresql://root:password#postgres/dbname'-> not working :(
IP address as 0.0.0.0 not working
IP address as 127.0.0.1 I can use only to run migrations/seeds but not to use the DB as GET/POST
I can use docker.internal.host but then cannot do the migration then
I'm getting always this error
getaddrinfo ENOTFOUND pokedex-db-postgres
I have no more ideas what is wrong so I'm sharing my configuration hoping someone will help me to understand
Docker file
# Builder
FROM node:17.3
RUN mkdir -p /home/node/code/node_modules && chown -R node:node /home/node/code
WORKDIR /home/node/code
COPY package*.json ./
USER node
RUN yarn install
COPY --chown=node:node . .
EXPOSE 8800
ENTRYPOINT [ "yarn", "run", "dev" ]
Docker compose
version: '3.9'
services:
node:
build: .
container_name: pokedex-backend-node
env_file:
- .env
depends_on:
postgresDB:
condition: service_started
ports:
- '8800:8800'
restart: always
volumes:
- ./:/home/node/code
postgresDB:
container_name: pokedex-db-postgres
env_file:
- .env
image: postgres:14.1
networks:
backend-database: null
postgres-pgadmin: null
expose:
- '5343:5432'
ports:
- '5343:5432'
restart: always
volumes:
- ./volumes/postgres-data:/var/lib/postgresql/data
- ./volumes/postgres-init:/docker-entrypoint-initdb.d
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U root']
interval: 10s
start_period: 10s
timeout: 4s
retries: 3
db-admin-pgadmin:
container_name: pokedex-dbadmin-pgadmin
depends_on:
postgresDB:
condition: service_started
env_file:
- .env
image: dpage/pgadmin4:latest
networks:
postgres-pgadmin: null
ports:
- '8900:80'
volumes:
- ./volumes/pgadmin-data:/var/lib/pgadmin
networks:
backend-database: {}
postgres-pgadmin: {}
Knex configuration
const development = {
client: 'pg',
connection: {
host: 'pokedex-db-postgres',
port: config.POSTGRES_PORT,
database: config.POSTGRES_DB,
user: config.POSTGRES_USER,
password: config.POSTGRES_PASSWORD,
},
pool: {
min: 5,
max: 50,
createTimeoutMillis: 3000,
acquireTimeoutMillis: 30000,
idleTimeoutMillis: 30000,
reapIntervalMillis: 1000,
createRetryIntervalMillis: 100,
afterCreate: function (conn, done) {
conn.query('SELECT 1;', function (err) {
if (err) {
log.error('Connection to DB failed %s', err);
}
done(err, conn);
});
},
},
debug: dev ? true : false,
migrations: {
directory: './src/database/migrations',
},
seeds: {
directory: './src/database/seeds',
},
useNullAsDefault: true,
};
Looks like you've defined the networks for pgadmin and postgres but didn't for the node app it explains why your node app doesn't see the other containers getaddrinfo ENOTFOUND pokedex-db-postgres

MySQL Docker Error: connect ECONNREFUSED 127.0.0.1:7201 to mysql container

Why is the connection refused to the mysql container?
(node:43) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:7201
users-service_1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1146:16)
users-service_1 | --------------------
users-service_1 | at Protocol._enqueue (/opt/app/node_modules/mysql/lib/protocol/Protocol.js:144:48)
users-service_1 | at Protocol.handshake (/opt/app/node_modules/mysql/lib/protocol/Protocol.js:51:23)
users-service_1 | at PoolConnection.connect (/opt/app/node_modules/mysql/lib/Connection.js:116:18)
users-service_1 | at Pool.getConnection (/opt/app/node_modules/mysql/lib/Pool.js:48:16)
users-service_1 | at /opt/app/src/driver/mysql/MysqlDriver.ts:894:18
users-service_1 | at new Promise (<anonymous>)
users-service_1 | at MysqlDriver.createPool (/opt/app/src/driver/mysql/MysqlDriver.ts:891:16)
users-service_1 | at MysqlDriver.<anonymous> (/opt/app/src/driver/mysql/MysqlDriver.ts:344:36)
users-service_1 | at step (/opt/app/node_modules/tslib/tslib.js:143:27)
users-service_1 | at Object.next (/opt/app/node_modules/tslib/tslib.js:124:57)
users-service_1 | (Use `node --trace-warnings ...` to show where the warning was created)
users-service_1 | (node:43) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
users-service_1 | (node:43) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
docker.compose.yml
version: "3"
services:
api-gateway:
build:
context: "."
dockerfile: "./api-gateway/Dockerfile"
depends_on:
- chat-service
- users-service
ports:
- "7000:7000"
volumes:
- ./api-gateway:/opt/app
chat-service:
build:
context: "."
dockerfile: "./chat-service/Dockerfile"
depends_on:
- chat-service-db
ports:
- "7100:7100"
volumes:
- ./chat-service:/opt/app
chat-service-db:
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=db
image: mysql:5.7.20
ports:
- "7200:3306"
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- "7300:80"
volumes:
- ./phpmyadmin/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php
users-service:
build:
context: "."
dockerfile: "./users-service/Dockerfile"
depends_on:
- users-service-db
ports:
- "7101:7101"
volumes:
- ./users-service:/opt/app
users-service-db:
environment:
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=db
- MYSQL_USER=root
- MYSQL_HOST=localhost
- MYSQL_ROOT_PASSWORD=password
restart: always
image: mysql:5.7.20
expose:
- 7201
ports:
- "7201:3306"
in the connection.ts
import config from "config";
import { Connection, createConnection } from "typeorm";
let connection: Connection;
export const initConnection = async () => {
connection = await createConnection({
type: "mysql",
host: "localhost",
port: 7201,
username: "root",
password: "password",
database: "db",
synchronize: false,
logging: false,
entities: ["./src/db/entities/*.ts"],
migrations: ["./src/db/migrations/*.ts"],
cli: {
entitiesDir: "./src/db/entities",
migrationsDir: "./src/db/migrations",
},
});
};
const getConnection = () => connection;
export default getConnection;
please help .don't know what to do it worked but after db migration with typeorm nothing worked i just dont know why do you have any ideas. Or need more code to solve the provblem would appriciate it
can you clarify the port and host names a little bit because in the docker-compose.yml the
users-service-db is
ports:
# <Port exposed> : < MySQL Port 7201 running inside container>
- '7201:3306' <===is the 7201 the port from outside of the container i don't get it?which port is what?
expose:
# Opens port 7201on the container
- '7201'
and in the typeOrmConfig.ts file the host is defined as localhost as you can see
export = {
type: "mysql",
host: "localhost",
port: 7201,
username: "root",
password: "password",
database: "db",
synchronize: false,
logging: false,
entities: ["./src/db/entities/**/*.ts"],
migrations: ["./src/db/migrations/**/*.ts"],
cli: {
entitiesDir: "./src/db/entities",
migrationsDir: "./src/db/migrations",
},
};
In that Docker-Compose constellation, your MySQL server isn't on localhost:7201 from the viewpoint of the application container(s), it's on users-service-db:7201.
Switch that in your database connection configuration.
You try changing 127.0.0.1:7201 to users-service-db:7201
You are using docker container, isolated environment, 127.0.0.1 cannot be accessed from other containers

Discord bot not able to contact discord servers when using docker compose

I recently started learning docker and have been running into issues when using docker-compose
The discord bot works perfectly when you use docker run but whenever I run docker-compose up, I get the following error
app_1 | /app/node_modules/discord.js/src/rest/RequestHandler.js:93
app_1 | throw new HTTPError(error.message, error.constructor.name, error.status, request.method, request.path);
app_1 | ^
app_1 |
app_1 | HTTPError [FetchError]: request to https://discord.com/api/v7/gateway/bot failed, reason: getaddrinfo EAI_AGAIN discord.com
app_1 | at RequestHandler.execute (/app/node_modules/discord.js/src/rest/RequestHandler.js:93:15)
app_1 | at processTicksAndRejections (node:internal/process/task_queues:93:5)
app_1 | at async RequestHandler.push (/app/node_modules/discord.js/src/rest/RequestHandler.js:39:14)
app_1 | at async WebSocketManager.connect (/app/node_modules/discord.js/src/client/websocket/WebSocketManager.js:138:9)
app_1 | at async Client.login (/app/node_modules/discord.js/src/client/Client.js:223:7) {
app_1 | code: 500,
app_1 | method: 'get',
app_1 | path: '/gateway/bot'
app_1 | }
app_1 | npm ERR! code 1
app_1 | npm ERR! path /app
app_1 | npm ERR! command failed
app_1 | npm ERR! command sh -c tsc && node dist/index.js
app_1 |
app_1 | npm ERR! A complete log of this run can be found in:
app_1 | npm ERR! /root/.npm/_logs/2021-01-11T03_27_59_096Z-debug.log
bot_app_1 exited with code 1
Here is my dockerfile
FROM node
WORKDIR /app
COPY package*.json ./
COPY .env ./
RUN npm install
COPY . .
CMD ["npm","start"]
Here is my docker-compose.yml file
version: '3.9'
services:
db:
image: postgres:13
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD
app:
build: .
volumes:
- app-data:/app/data
depends_on:
- db
env_file: .env
environment:
POSTGRES_HOST: db
volumes:
app-data: {}
db-data: {}
And here is my main code which helps me connect to discord
import { Client, Message, Guild } from "discord.js";
import { commands } from "./commands/index";
import { config } from "dotenv";
export const client = new Client();
config();
client.on("ready", async () => {
const guild = await client.guilds.fetch("771187253937438762");
console.log(`Logged in as ${client.user.tag}!`);
client.user.setActivity(`over ${guild.memberCount} furries`, {
type: "WATCHING",
});
});
client.on("message", async (msg) => {
if (msg.author.bot) return;
if (msg.author.id == client.user?.id) return;
if (!msg.content.startsWith(process.env.BOT_PREFIX)) return;
const [cmd, ...args] = msg.content
.slice(process.env.BOT_PREFIX.length)
.replace(/ +/g, " ")
.split(" ");
const commandClass = commands.find((command) => {
return command.aliases.some((c) => c.toLowerCase() === cmd.toLowerCase());
});
if (!commandClass) return;
await commandClass.execute({
msg: msg as Message & { guild: Guild },
cmd,
args: args,
}).catch((e)=>{
console.log(e);
});
});
client.login(process.env.DISCORD_TOKEN);
If anyone can help me with this question that would be great.
You are missing the network for your discord bot in your docker-compose.yml
network_mode: bridge - This is the easiest way to get it to work
You can incorperate this into the compose file like:
version: '3.9'
services:
db:
image: postgres:13
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD
app:
build: .
volumes:
- app-data:/app/data
depends_on:
- db
env_file: .env
environment:
POSTGRES_HOST: db
network_mode: bridge
volumes:
app-data: {}
db-data: {}
You can read more about the network types in the docs

Can't connect Elasticsearch from my Nodejs app: connect ECONNREFUSED 127.0.0.1:9200

I cannot connect to Elasticsearch docker server from my NodeJS application.
My code
This is my docker-compose file:
version: "3.7"
services:
backend:
container_name: vstay-api
ports:
- "4000:4000"
build:
context: .
dockerfile: Dockerfile
env_file:
- ./.env
environment:
- DB_URI=mongodb://mongo:27017/vstay-db
- DB_HOST=mongo
- DB_PORT=27017
restart: always
links:
- mongo
- elasticsearch
mongo:
image: mongo:4.2
ports:
- "9000:27017"
container_name: vstay-db
restart: always
volumes:
- "./data/mongo:/data/db"
environment:
- DB_HOST=mongo
- DB_PORT=27017
command: mongod
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.9.3
container_name: vstay_elasticsearch
environment:
- node.name=elasticsearch
- cluster.name=datasearch
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- cluster.initial_master_nodes=elasticsearch
ports:
- 9200:9200
- 9300:9300
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./data/elastic:/usr/share/elasticsearch/data
kibana:
image: docker.elastic.co/kibana/kibana:7.9.3
container_name: vstay_kibana
logging:
driver: none
elastic.js
const { Client } = require("#elastic/elasticsearch");
module.exports.connectES = () => {
try {
const client = new Client({
node: "http://localhost:9200",
maxRetries: 5,
requestTimeout: 60000,
sniffOnStart: true,
});
client.ping(
{
// ping usually has a 3000ms timeout
requestTimeout: Infinity,
// undocumented params are appended to the query string
hello: "elasticsearch!",
},
function (error) {
if (error) {
console.log(error);
console.trace("elasticsearch cluster is down!");
} else {
console.log("All is well");
}
}
);
return client;
} catch (error) {
console.log(error);
process.exit(0);
}
};
And index.js to connect:
const { app } = require("./config/express");
const { connect: dbConnect } = require("./config/mongo");
const { connectES } = require("./config/elastic");
const { port, domain, env } = require("./config/vars");
let appInstance;
const startApp = async () => {
const dbConnection = await dbConnect();
const ESConnection = await connectES();
app.locals.db = dbConnection;
app.locals.ESClient = ESConnection;
app.listen(port, () =>
console.log(`Server is listening on ${domain.API} (${env})`)
);
return app;
};
appInstance = startApp();
module.exports = { appInstance };
Error
I have an application that is dockerized (NodeJS and Elasticsearch - v7.9.3). The server could be started well, but when I tried to create a Client instance in Elasticsearch, it showed me an error:
ConnectionError: connect ECONNREFUSED 127.0.0.1:9200
at ClientRequest.<anonymous> (/app/node_modules/#elastic/elasticsearch/lib/Connection.js:109:18)
at ClientRequest.emit (events.js:210:5)
at Socket.socketErrorListener (_http_client.js:406:9)
at Socket.emit (events.js:210:5)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
name: 'ConnectionError',
meta: {
body: null,
statusCode: null,
headers: null,
meta: {
context: null,
request: [Object],
name: 'elasticsearch-js',
connection: [Object],
attempts: 5,
aborted: false
}
}
}
The server of Elasticsearch and Kibana are started, I can connect it on my browser at: http://localhost:9200 and http://localhost:5601.
But when I connect from my nodeJS app, it still shows error. I also tried to find my Container IP and replace it with 'localhost' but it still not working.
Can anyone help me to resolve this? Thanks.
My Environment
node version: v10.19.0
#elastic/elasticsearch version: 7.9.3
os: Linux
Enviroment: Docker
when you run the docker-compose file, the elasticsearch service instance will not be available to your backend service at localhost. change http://localhost:9200 to http://elasticsearch:9200 in your node.js code.
docker compose automatically creates dns entries with same name as the service name for each service.
Following solution works for me
http://127.0.0.1:9200

mongoose failing to connect in docker-compose

I've got a simple docker-compose.yml that looks like this:
services:
mongodb-service:
image: mongo:latest
command: "mongod --bind_ip_all"
mongodb-seeder:
image: mongo:latest
depends_on:
- mongodb-service
command: "mongoimport --uri mongodb://mongodb-service:27017/auth --drop --file /tmp/users.json"
myapp:
image: myapp:latest
environment:
DATABASEURL: mongodb://mongodb-service:27017/auth
depends_on:
- mongodb-service
myapp is a nodejs app that uses mongoose to connect to a mongodb database like so:
const databaseURL = process.env.DATABASEURL;
async function connectToMongo() {
try {
return await mongoose.connect(databaseURL, {
useUnifiedTopology: true,
useNewUrlParser: true,
useCreateIndex: true,
});
}
catch (error) {
logger.error('MongoDB connect failure.', error);
}
}
mongodb-seeder works perfectly fine. I can kick it off, it connects to mongodb-service and runs the import without any problems. However, myapp starts up, tries to connect to mongodb-service for 30 seconds, then dies:
ERROR 2020-09-16T12:13:21.427 [MAIN] MongoDB connection error! [Arguments] {
'0': MongooseError [MongooseTimeoutError]: Server selection timed out after 30000 ms
...stacktrace snipped...
at Function.Module._load (internal/modules/cjs/loader.js:724:14) {
message: 'Server selection timed out after 30000 ms',
name: 'MongooseTimeoutError',
reason: Error: connect ECONNREFUSED 127.0.0.1:27017
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1128:14) {
name: 'MongoNetworkError',
[Symbol(mongoErrorContextSymbol)]: {}
},
[Symbol(mongoErrorContextSymbol)]: {}
}
}
Note: The IP address in this log says it tried to connect to 127.0.0.1, not mongodb://mongodb-service:27017/auth. No matter what value I put in for DATABASEURL, it keeps printing 127.0.0.1. Any ideas why I can't get mongoose to recognize the hostname I'm giving it? And why would mongoose not be able to connect to a service that's clearly network-visible, since another container (mongodb-seeder) can see it without any problems?
Edit: I'm using mongoose 5.8.7
I was able to solve this on my own, turns out it was a pretty stupid miss on my part.
The DockerFile for my app defined an entrypoint that executed a script that exported the DATABASEURL prior to running. Removing that export allowed my environment: settings to flow down to the nodejs app.

Resources