Reputation: 5979
I have a project with this directory structure:
- other-service/
- my-service/
src/
Dockerfile
.env
docker-compose
.env
I have defined my mongoDB container & service container in a docker-compose.yml file like below:
version: "3"
services:
my-service:
depends_on:
- mongodb
env_file: ./my-service/.env
container_name: my-service
build: ./my-service
environment:
- DB_HOST=$DB_HOST
- DB_USER=$DB_USER
- DB_PASSWORD=$DB_PASSWORD
- DB_NAME=$DB_NAME
- DB_PORT=$DB_PORT
ports:
- "3002:3002"
mongodb:
image: mongo:latest
container_name: my-mongodb
env_file: ./.env
environment:
MONGO_INITDB_ROOT_USERNAME: $DB_USER
MONGO_INITDB_ROOT_PASSWORD: $DB_PASSWORD
ports:
- $DB_PORT:$DB_PORT
volumes:
- db_vol:/data/db
volumes:
db_vol:
The my-service/.env
file looks like this:
DB_HOST=mongodb
DB_USER=root
DB_PASSWORD=pass123
DB_NAME=my_db
DB_PORT=27017
...
The root level .env
looks like this (basically the same content as my-service/.env
for the DB part):
#used by compose
DB_HOST=mongodb
DB_USER=root
DB_PASSWORD=pass123
DB_NAME=my_db
DB_PORT=27017
my-service
tries to connect to mongoDB with this code:
const dbUri=`mongodb://${process.env['DB_USER']}:${process.env['DB_PASSWORD']}@${process.env['DB_HOST']}:${process.env['DB_PORT']}/${process.env['DB_NAME']}`
console.log(`DB connect to: ${dbUri}`);
await mongoose.connect(dbUri, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
After I run docker-compose build
& docker-compose up -d
. The my-mongodb
container is up and running. But my-service
is not. I checked the container log, it shows:
DB connect to: mongodb://root:pass123@mongodb:27017/my_db
...
DatabaseConnError: Database connection failure. undefined
...
statusCode: 500,
msg: 'Database connection failure'
}
Node.js v19.2.0
I feel it is because both containers are on the same Docker bridge network, the database URI I defined might not correct? But I am not sure. Could someone please guide me where could be wrong in my case?
=== UPDATE on 8th of December2022 ===
I dug deeper of my problem, it turned out the problem is actually an AuthenticationError
, full error log is below:
Database connection failure. {"ok":0,"code":18,"codeName":"AuthenticationFailed","name":"MongoError"}
It is the same issue @jeeves' answer below has mentioned, then I tried adding ?authSource=admin
like @jeeves suggested:
DB connect to: mongodb://root:pass123@mongodb:27017/my_db?authSource=admin
but I still get the authentication error. Why?
Upvotes: 2
Views: 1012
Reputation: 2031
I'm not sure where the problem here is. I certainly had a few issues authenticating with the DB but I believe that that is an issue with the database itself (and my lack of understanding of it ;)) and not a docker-compose/ networking problem.
Here is a stripped back (but working) version.
Directory structure
docker-compose file
version: "3"
services:
my-service:
depends_on:
- mongodb
container_name: my-service
build: ./my-service
environment:
- DB_HOST=mongodb
- DB_USER=root
- DB_PASSWORD=password123
- DB_NAME=test
- DB_PORT=27017
ports:
- "3002:3002"
mongodb:
image: mongo:latest
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password123
ports:
- "27017:27017"
Dockerfile
FROM node:19
WORKDIR /usr/src/app
COPY . .
RUN npm install
USER node
CMD ["node", "index.js"]
And my index.js
Note: added following query param ?authSource=admin
to connection string.
const mongoose = require('mongoose');
console.log(process.env);
const dbUri=`mongodb://${process.env['DB_USER']}:${process.env['DB_PASSWORD']}@${process.env['DB_HOST']}:${process.env['DB_PORT']}/${process.env['DB_NAME']}?authSource=admin`
console.log(dbUri, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
mongoose.connect(dbUri).then(() => console.log('is connected'))
.catch((error) => console.log(error));
Then execute following:
$ cd demo
$ docker-compose build
$ docker-compose up mongodb
$ docker-compose up my-service
Output from my-service:
$ docker-compose up my-service
demo_mongodb_1 is up-to-date
Recreating my-service ... done
Attaching to my-service
my-service | {
my-service | NODE_VERSION: '19.2.0',
my-service | HOSTNAME: 'ea324ba32274',
my-service | DB_PORT: '27017',
my-service | YARN_VERSION: '1.22.19',
my-service | HOME: '/home/node',
my-service | DB_NAME: 'test',
my-service | PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
my-service | DB_PASSWORD: 'password123',
my-service | PWD: '/usr/src/app',
my-service | DB_HOST: 'mongodb',
my-service | DB_USER: 'root'
my-service | }
my-service | mongodb://root:password123@mongodb:27017/test?authSource=admin
my-service | (node:1) [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.
my-service | (Use `node --trace-deprecation ...` to show where the warning was created)
my-service | is connected
The additional query string is doing nothing for connectivity between containers. I was getting an authentication error when connecting - but that still meant containers had connectivity.
Hope this helps
Upvotes: 0
Reputation: 1611
you might need a healthcheck for mongodb.
version: "3"
services:
my-service:
depends_on:
mongodb:
condition: service_healthy
env_file: ./my-service/.env
container_name: my-service
build: ./my-service
environment:
- DB_HOST=$DB_HOST
- DB_USER=$DB_USER
- DB_PASSWORD=$DB_PASSWORD
- DB_NAME=$DB_NAME
- DB_PORT=$DB_PORT
ports:
- "3002:3002"
mongodb:
image: mongo:latest
container_name: my-mongodb
env_file: ./.env
environment:
MONGO_INITDB_ROOT_USERNAME: $DB_USER
MONGO_INITDB_ROOT_PASSWORD: $DB_PASSWORD
ports:
- $DB_PORT:$DB_PORT
volumes:
- db_vol:/data/db
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh localhost:$DB_PORT/test --quiet
interval: 10s
timeout: 10s
retries: 5
start_period: 10s
volumes:
db_vol:
Similar: mongodb and mongo-express not connecting with docker-compose
Upvotes: 2