简体   繁体   English

服务容器无法使用 docker-compose 连接到 MongoDB 容器

[英]service container fails at connecting to MongoDB container with docker-compose

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:我在 docker-compose.yml 文件中定义了我的 mongoDB 容器和服务容器,如下所示:

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: my-service/.env文件如下所示:

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):根级.env看起来像这样(与数据库部分的my-service/.env内容基本相同):

#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: my-service尝试使用以下代码连接到 mongoDB:

 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 .在我运行docker-compose build & docker-compose up -d之后。 The my-mongodb container is up and running. my-mongodb容器已启动并正在运行。 But my-service is not.my-service不是。 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?我感觉是因为两个容器都在同一个 Docker bridge.network 上,我定义的数据库 URI 可能不正确? But I am not sure.但我不确定。 Could someone please guide me where could be wrong in my case?有人可以指导我在我的情况下哪里可能出错吗?

=== UPDATE on 8th of December2022 === === 2022 年 12 月 8 日更新 ===

I dug deeper of my problem, it turned out the problem is actually an AuthenticationError , full error log is below:我深入研究了我的问题,结果发现问题实际上是AuthenticationError ,完整的错误日志如下:

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:这是@jeeves 在下面的回答中提到的同一个问题,然后我尝试添加?authSource=admin就像@jeeves 建议的那样:

DB connect to: mongodb://root:pass123@mongodb:27017/my_db?authSource=admin

but I still get the authentication error.但我仍然收到身份验证错误。 Why?为什么?

you might need a healthcheck for mongodb.您可能需要对 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类似: mongodb 和 mongo-express 未连接 docker-compose

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.我在使用数据库进行身份验证时确实遇到了一些问题,但我认为这是数据库本身的问题(以及我对它缺乏了解;)),而不是 docker-compose/.networking 问题。

Here is a stripped back (but working) version.这是一个精简(但有效)的版本。

Directory structure目录结构

在此处输入图像描述

docker-compose file docker-compose 文件

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 Dockerfile

FROM node:19

WORKDIR /usr/src/app
COPY . .
RUN npm install
USER node
CMD ["node", "index.js"]

And my index.js还有我的 index.js

Note: added following query param ?authSource=admin to connection string.注意:添加以下查询参数?authSource=admin到连接字符串。

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: Output 来自我的服务:

$ 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希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM