Docker config:
FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ]
Docker compose:
version: "2"
services:
web:
build: .
depends_on:
- mongo
mongo:
image: mongo
ports:
- "27017:27017"
package.json:
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "",
"author": "Stepan Yakovenko <stiv.yakovenko#gmail.com>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {"express": "^4.16.1","mongodb": "~3.0.1","monk": "~6.0.5" }
}
server.js:
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('mongo:27017/nodetest1');
db.then(function(){console.log("hello"});
Most of the time it works, but if I purge docker cache, usually it doesn't work and gives me this:
web_1 | (node:15) UnhandledPromiseRejectionWarning: MongoError: failed to connect to server [mongo:27017] on first connect [MongoErr
or: connect ECONNREFUSED 172.18.0.2:27017]
The root cause I think that docker's depends_on doesn't guarantee me that mongo has started listening, because in this case I get listening message from mongo after this error. How can I fix this? Does docker has any fix for this situation? Or how can I ask mongo to try connecting forever?
Thanx
This is sample reconnect code, which worked for me:
var connect = function () {
var db = monk('mongo:27017/nodetest1');
db.then(function () {
console.log("connected");
}).catch(function () {
// sometimes node starts before mongo, so we have to reconnect in case of error
connect();
});
};
connect();
Related
I have a custom made docker image for the backend of my app. I have a yaml file that runs my app image and a mongo image. However, when I use docker-compose on the yml file, I get the following error (about 20 seconds and the containers start running):
(node:33) [MONGOOSE] DeprecationWarning: Mongoose: the `strictQuery` option will be switched back to `false` by default in Mongoose 7. Use `mongoose.set('strictQuery', false);` if you want to prepare for this change. Or use `mongoose.set('strictQuery', true);` to suppress this warning.
(Use `node --trace-deprecation ...` to show where the warning was created)
Server listening on port 3000
/cloudband/node_modules/mongoose/lib/connection.js:825
const serverSelectionError = new ServerSelectionError();
^
MongooseServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
at Connection.openUri (/cloudband/node_modules/mongoose/lib/connection.js:825:32)
at /cloudband/node_modules/mongoose/lib/index.js:409:10
at /cloudband/node_modules/mongoose/lib/helpers/promiseOrCallback.js:41:5
at new Promise (<anonymous>)
at promiseOrCallback (/cloudband/node_modules/mongoose/lib/helpers/promiseOrCallback.js:40:10)
at Mongoose._promiseOrCallback (/cloudband/node_modules/mongoose/lib/index.js:1262:10)
at Mongoose.connect (/cloudband/node_modules/mongoose/lib/index.js:408:20)
at Object.<anonymous> (/cloudband/server/server.js:15:4)
at Module._compile (node:internal/modules/cjs/loader:1239:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1293:10) {
reason: TopologyDescription {
type: 'Unknown',
servers: Map(1) {
'localhost:27017' => ServerDescription {
address: 'localhost:27017',
type: 'Unknown',
hosts: [],
passives: [],
arbiters: [],
tags: {},
minWireVersion: 0,
maxWireVersion: 0,
roundTripTime: -1,
lastUpdateTime: 28094812,
lastWriteDate: 0,
error: MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017
at connectionFailureError (/cloudband/node_modules/mongodb/lib/cmap/connect.js:387:20)
at Socket.<anonymous> (/cloudband/node_modules/mongodb/lib/cmap/connect.js:310:22)
at Object.onceWrapper (node:events:628:26)
at Socket.emit (node:events:513:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
cause: Error: connect ECONNREFUSED 127.0.0.1:27017
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 27017
},
[Symbol(errorLabels)]: Set(1) { 'ResetPool' }
},
topologyVersion: null,
setName: null,
setVersion: null,
electionId: null,
logicalSessionTimeoutMinutes: null,
primary: null,
me: null,
'$clusterTime': null
}
},
stale: false,
compatible: true,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
setName: null,
maxElectionId: null,
maxSetVersion: null,
commonWireVersion: 0,
logicalSessionTimeoutMinutes: null
},
code: undefined
}
Here are my files:
Dockerfile:
FROM node:19.4.0
WORKDIR /cloudband
COPY package.json /cloudband/
COPY package-lock.json /cloudband/
RUN npm ci
COPY .env /cloudband/
COPY server /cloudband/server/
EXPOSE 3000
CMD ["npm", "run", "dev:server"]
YAML file:
version: '3'
services:
mongo:
image: mongo
container_name: mongo
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
cloudband:
image: cloudband
container_name: cloudband
ports:
- 3000:3000
command: npm run dev:server
networks:
app:
I expected my application and mongo db to start running in their respective containers and for them to be able to communicate (i.e. create documents / find documents / etc.).
What I have already tried:
-making sure they are in the same network (they are)
-making sure they can ping each other (they can)
-adding links to my app in the yaml file
-checked configurations and i think they are ok (port, host, ip)
-switching my uri to the following things:
# MONGO_URI_=mongodb://admin:password#localhost:27017/dbname
MONGO_URI_=mongodb://localhost:27017/dbname
# MONGO_URI_=mongodb://127.0.0.1:27017/dbname
Things to consider:
node v18.12.0 is installed on my computer
In a container, localhost means the container itself.
Docker-compose creates a docker network where the containers can talk to each other using their service name or container names as host names.
So, instead of
MONGO_URI_=mongodb://localhost:27017/dbname
you need to use
MONGO_URI_=mongodb://mongo:27017/dbname
I'm having trouble creating a mongo database using the docker-compose command. Docker desktop tells me that everything is up and running including the db, but all I get is the standard 'admin, config, local' not the db I want to create. Here's my docker-compose.yaml
version: '3'
services:
app:
build: ./
entrypoint: ./.docker/entrypoint.sh
ports:
- 3000:3000
volumes:
- .:/home/node/app
depends_on:
- db
db:
image: mongo:4.4.4
restart: always
volumes:
- ./.docker/dbdata:/data/db
- ./.docker/mongo:/docker-entrypoint-initdb.d
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=root
- MONGO_INITDB_DATABASE=nest
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
- ME_CONFIG_MONGODB_SERVER=db
- ME_CONFIG_MONGODB_AUTH_USERNAME=root
- ME_CONFIG_MONGODB_AUTH_PASSWORD=root
- ME_CONFIG_MONGODB_ADMINUSERNAME=root
- ME_CONFIG_MONGODB_ADMINPASSWORD=root
depends_on:
- db
my init.js inside .docker/mongo
db.routes.insertMany([
{
_id: "1",
title: "Primeiro",
startPosition: {lat: -15.82594, lng: -47.92923},
endPosition: {lat: -15.82942, lng: -47.92765},
},
{
_id: "2",
title: "Segundo",
startPosition: {lat: -15.82449, lng: -47.92756},
endPosition: {lat: -15.82776, lng: -47.92621},
},
{
_id: "3",
title: "Terceiro",
startPosition: {lat: -15.82331, lng: -47.92588},
endPosition: {lat: -15.82758, lng: -47.92532},
}
]);
and my dockerfile
FROM node:14.18.1-alpine
RUN apk add --no-cache bash
RUN npm install -g #nestjs/cli
USER node
WORKDIR /home/node/app
and this is the 'error' log I get from docker when I run the nest container with mongodb, nest app and mongo express(there is actually a lot more but SO keeps thinking that it is spam for some reason.
about to fork child process, waiting until server is ready for connections.
Successfully added user: {
"user" : "root",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
Error saving history file: FileOpenFailed Unable to open() file /home/mongodb/.dbshell: No such file or directory
{"t":{"$date":"2022-06-01T19:39:15.542+00:00"},"s":"I", "c":"NETWORK", "id":22944, "ctx":"conn2","msg":"Connection ended","attr":{"remote":"127.0.0.1:39304","connectionId":2,"connectionCount":0}}
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init.js
{"t":{"$date":"2022-06-01T19:39:15.683+00:00"},"s":"I", "c":"NETWORK", "id":22943, "ctx":"listener","msg":"Connection accepted","attr":{"remote":"127.0.0.1:39310","connectionId":3,"connectionCount":1}}
{"t":{"$date":"2022-06-01T19:39:15.684+00:00"},"s":"I", "c":"NETWORK", "id":51800, "ctx":"conn3","msg":"client metadata","attr":{"remote":"127.0.0.1:39310","client":"conn3","doc":{"application":{"name":"MongoDB Shell"},"driver":{"name":"MongoDB Internal Client","version":"4.4.4"},"os":{"type":"Linux","name":"Ubuntu","architecture":"x86_64","version":"18.04"}}}}
{"t":{"$date":"2022-06-01T19:39:15.701+00:00"},"s":"I", "c":"STORAGE", "id":20320, "ctx":"conn3","msg":"createCollection","attr":{"namespace":"nest.routes","uuidDisposition":"generated","uuid":{"uuid":{"$uuid":"f689868e-af6d-4ec6-b555-dcf520f24788"}},"options":{}}}
{"t":{"$date":"2022-06-01T19:39:15.761+00:00"},"s":"I", "c":"INDEX", "id":20345, "ctx":"conn3","msg":"Index build: done building","attr":{"buildUUID":null,"namespace":"nest.routes","index":"_id_","commitTimestamp":{"$timestamp":{"t":0,"i":0}}}}
uncaught exception: ReferenceError: colection is not defined :
#/docker-entrypoint-initdb.d/init.js:23:1
failed to load: /docker-entrypoint-initdb.d/init.js
exiting with code -3
this is what running docker-compose ps shows
NAME COMMAND SERVICE STATUS PORTS
nest-api-app-1 "./.docker/entrypoin…" app running 0.0.0.0:3000->3000/tcp
nest-api-db-1 "docker-entrypoint.s…" db running 27017/tcp
nest-api-mongo-express-1 "tini -- /docker-ent…" mongo-express running 0.0.0.0:8081->8081/tcp
this what my docker desktop shows
The MongoDB container only creates a database if no database already exists. You probably already have one, which is why a new database isn't created and your initialization script isn't run.
Delete the contents of ./.docker/dbdata on the host. Then start the containers with docker-compose and Mongo should create your database for you.
I am using docker compose with my app and are trying to connect mongodb to the server. When i run my app locally outside of docker i get this as output(works as intended)
[nodemon] 2.0.15
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
Server running
Mongoose connected to db...
Mongodb connected....
When i run the docker-compose up command and the server runs in the container i get this output
[nodemon] 2.0.15
docker-server | [nodemon] to restart at any time, enter `rs`
docker-server | [nodemon] watching path(s): *.*
docker-server | [nodemon] watching extensions: js,mjs,json
docker-server | [nodemon] starting `node index.js`
docker-server | Works
docker-server | Works
docker-server | Mongoose connection is disconnected...
After a while the mongoose disconnects.
My package.json is
{
"name": "make-me-a-sandwich",
"version": "1.1.0",
"description": "This is the Swagger 2.0 API for Web Architectures course group project work. ",
"main": "index.js",
"scripts": {
"prestart": "npm install",
"start": "nodemon index.js"
},
"keywords": [
"swagger"
],
"license": "Unlicense",
"private": true,
"dependencies": {
"connect": "^3.2.0",
"js-yaml": "^3.3.0",
"swagger-tools": "0.10.1",
"mongoose": "^6.1.5",
"nodemon": "^2.0.15"
}
}
My index.js file is
const http = require('http');
const connect = require('./models/db');
const PORT = 80;
const server = http.createServer(function (request, response) {
const { url, method, headers } = request;
const filePath = new URL(url, `http://${headers.host}`).pathname;
if (filePath === '/' && method.toUpperCase() === 'GET') {
console.log("Works")
response.statusCode = 200;
response.setHeader('Content-Type', 'text/plain');
response.end('Hello, World! GET\n');
} else {
response.statusCode = 200;
response.setHeader('Content-Type', 'text/plain');
response.end('Hello, World! Teemu\n');
}
});
server.on('error', err => {
console.error(err);
server.close();
});
server.on('close', () => console.log('Server closed.'));
server.listen(PORT, () => {
console.log("Server running");
});
connect.connectDB();
model/db.js
const mongoose = require('mongoose');
function connectDB() {
mongoose
.connect('mongodb://mongo_db:27017', {
useNewUrlParser: true,
})
.then(() => {
console.log('Mongodb connected....');
})
.catch(err => console.log(err.message));
mongoose.connection.on('connected', () => {
console.log('Mongoose connected to db...');
});
mongoose.connection.on('error', err => {
console.log(err.message);
});
mongoose.connection.on('disconnected', () => {
console.log('Mongoose connection is disconnected...');
});
};
function disconnectDB() {
mongoose.disconnect();
}
module.exports = { connectDB, disconnectDB };
Dockerfile
FROM node:17.3.0
WORKDIR /server
COPY package.json .
RUN npm install
COPY . .
EXPOSE 80
CMD ["npm", "start"]
docker-compose file
version: "3"
services:
server-a:
container_name: docker-server
build:
dockerfile: Dockerfile
context: ./backend/server-a
ports:
- "3000:80"
links:
- mongo_db
networks:
- backend
mongo_db:
container_name: mongo
image: mongo:latest
ports:
- '27017:27017'
networks:
backend:
Help would be really appreciated. Let me also know if i can offer any other information.
Different containers need to be on the same Compose network to communicate. If a service doesn't have a networks: block, Compose automatically attaches it to a default network. So in your example, the server-a container is only on the backend network, but the mongo_db container is only on the default network, and that's why they can't communicate.
The easiest way to resolve this is to delete all of the networks: blocks in the file. Then Compose will attach all of the containers to the default network. Removing other unnecessary options, you could reduce this Compose file to just
version: "3.8"
services:
server-a:
build: ./backend/server-a
ports:
- "3000:80"
mongo_db:
image: mongo:latest
ports:
- '27017:27017'
In a comment you suggest that it's important to keep a second named network. If that's the case, then you need to make sure the database container also has a networks: block that names a network in common with the application container.
I deployed Strapi CMS to Heroku, but I get this error
Error connecting to the Mongo database. Server selection timed out after 30000 ms
Log:
2020-05-27T17:43:55.398256+00:00 heroku[web.1]: Starting process with command `npm start`
2020-05-27T17:43:58.724121+00:00 app[web.1]:
2020-05-27T17:43:58.724143+00:00 app[web.1]: > strapi-oskogen-mongodb#0.1.0 start /app
2020-05-27T17:43:58.724143+00:00 app[web.1]: > strapi start
2020-05-27T17:43:58.724143+00:00 app[web.1]:
2020-05-27T17:44:02.234160+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'count' of module exports inside circular dependency
2020-05-27T17:44:02.234179+00:00 app[web.1]: (Use `node --trace-warnings ...` to show where the warning was created)
2020-05-27T17:44:02.234732+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'findOne' of module exports inside circular dependency
2020-05-27T17:44:02.234879+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'remove' of module exports inside circular dependency
2020-05-27T17:44:02.235021+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'updateOne' of module exports inside circular dependency
2020-05-27T17:44:32.238852+00:00 app[web.1]: [2020-05-27T17:44:32.238Z] debug ⛔️ Server wasn't able to start properly.
2020-05-27T17:44:32.253150+00:00 app[web.1]: [2020-05-27T17:44:32.253Z] error Error connecting to the Mongo database. Server selection timed out after 30000 ms
My environments settings:
database.js
** server.js **
** response.js **
** config vars **
Site works well on localhost with both dev and prod environment. So it connects to MongoDB on Atlas and no problem with that.
I do not have any addons installed on Heroku.
** packages.json **
On Atlas side I opened all IPs in white list.
Any idea? Thank you! :)
My configuration for deployment of Strapi 3.0.1 on Heroku, both for develop and production environments:
module.exports = ({ env }) => ({
defaultConnection: "default",
connections: {
default: {
connector: "mongoose",
settings: {
uri: env("DATABASE_URI"),
ssl: { rejectUnauthorized: false }
},
options: {
ssl: true,
authenticationDatabase: "",
useUnifiedTopology: true,
pool: {
min: 0,
max: 10,
idleTimeoutMillis: 30000,
createTimeoutMillis: 30000,
acquireTimeoutMillis: 30000
}
},
},
},
});
server.js
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 443), <-- 443 was critical to make it work on production
});
.env - local file
DATABASE_URI="mongodb+srv://OdegXXXXXUser:OXXXX20#odXXXXcluster-h9o2e.mongodb.net/odeXXXXXndb?retryWrites=true&w=majority"
HOST="0.0.0.0"
PORT="1337"
Vars on Heroku:
DATABASE_URI er identical as on localhost, the same database.
I hope it will help to anybody :-)
make this your database.json
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "mongoose",
"settings": {
"client": "mongo",
"host": "${process.env.DATABASE_HOST}",
"port": "${process.env.DATABASE_PORT}",
"database": "${process.env.DATABASE_NAME}",
"username": "${process.env.DATABASE_USERNAME}",
"password": "${process.env.DATABASE_PASSWORD}",
},
"options": {}
}
}
}
Also make sure to add package-lock.json to your git.ignore file.
then do
git add .
git commit -m "(message) "
git push heroku master
then
heroku open
Start your app servers too
I'm trying to connect to mongodb running in docker from the app running on host using mongoose but it failed.
I can't use the port 27017 for the new mongodb container because it is used by other container. So I followed the guide here for setting it up using the compose.
Below are the snippets:
docker-compose.yml
version: '3'
services:
db:
image: mongo:latest
restart: always
ports:
- '8081:8081'
environment:
MONGO_INITDB_ROOT_USERNAME: root1
MONGO_INITDB_ROOT_PASSWORD: password1
But when I do docker-ps, port 27017 still there but I'm not sure if that causes an issue.
PORTS
0.0.0.0:8081->8081/tcp, 27017/tcp
Then I created a new user in admin database.
use admin
db.createUser(
{
user: "admin1",
pwd: "password2",
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
}
)
server.js
const connectOption = {
useNewUrlParser: true,
user: 'admin1',
pass: 'password2',
authSource: 'admin',
}
const mongoURL = 'mongodb://localhost:8081/app1';
mongoose.connect(mongoURL, connectOption)
.then(() => console.log('MongoDB Connected'))
.catch(error => console.log(error));
And the error I received is
{
MongoNetworkError: failed to connect to server [localhost:8081] on first connect [MongoNetworkError: write EPIPE]
...
...
...
name: 'MongoNetworkError',
errorLabels: [ 'TransientTransactionError' ],
[Symbol(mongoErrorContextSymbol)]: {}
}
Assuming you're running nodejs application as a docker-compose service, in db service remove ports section (including - '8081:8081'
line). In server.js, change const mongoURL = 'mongodb://localhost:8081/app1'; to const mongoURL = 'mongodb://db:27017/app1';.
If you want to access the db from host machine, change ports 8081:8081 to <give-a-port-number>:27017.