通过Docker Compose部署后NestJS/MongoDB认证失败排查
MongoDB部署后认证失败问题排查
问题背景
本地环境下使用root用户或自建用户连接MongoDB时认证正常,但通过Coolify/Dokploy将服务部署到服务器后,出现认证失败错误,日志提示MongoServerError: Authentication failed.。相关配置信息如下:
Docker Compose 配置
version: '3.8' services: mongodb-dev: image: mongo:latest container_name: mongodb-dev restart: always # env_file: ${ENV_FILE:-.env} environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD} MONGO_INITDB_DATABASE: ${MONGO_INITDB_DATABASE} ports: - '27017:27017' volumes: - mongodbdata:/data/db - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro # This should be executed by Mongo during startup networks: - my-network my-nest-backend: build: . container_name: my-nest-backend ports: - '${PORT}:${PORT}' depends_on: - mongodb-dev networks: - my-network # env_file: ${ENV_FILE:-.env} environment: DATABASE_NAME: ${DATABASE_NAME} DATABASE_USER: ${DATABASE_USER} DATABASE_PASS: ${DATABASE_PASS} MONGODB_HOST: ${MONGODB_HOST} NODE_ENV: ${NODE_ENV} PORT: ${PORT} MONGO_URI: mongodb://${DATABASE_USER}:${DATABASE_PASS}@${MONGODB_HOST}:27017/${DATABASE_NAME}?authSource=admin&directConnection=true command: npm run start:debug volumes: mongodbdata: networks: my-network: driver: bridge
NestJS 配置
@Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), MongooseModule.forRootAsync({ useFactory: async () => { const logger = new Logger('MongooseModule'); const uri = process.env.MONGO_URI; try { // Establish a MongoDB connection with the provided URI return { uri, useNewUrlParser: true, useUnifiedTopology: true }; } catch (error) { logger.error(`MyLog Failed to connect to MongoDB: ${error.message}`, error.stack); throw error; // Rethrow to prevent app from starting with bad DB connection } }, }), QuoteModule, PhilosopherModule, AuthModule, ], controllers: [AppController], providers: [AppService], }) export class AppModule implements OnModuleInit { private readonly logger = new Logger(AppModule.name); async onModuleInit() { this.logger.log('MyLog AppModule initialized'); } }
错误日志
MongoServerError: Authentication failed. at Connection.sendCommand (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/connection.js:297:27) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async Connection.command (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/connection.js:325:26) at async executeScram (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/auth/scram.js:79:22) at async ScramSHA1.auth (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/auth/scram.js:39:16) at async performInitialHandshake (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/connect.js:101:13) at async connect (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/connect.js:19:9)
可能的原因及解决方法
1. 环境变量未正确注入
- 部署平台可能未正确加载
.env文件中的变量,导致DATABASE_USER、DATABASE_PASS等参数为空或错误,生成的连接字符串无效。 - 排查:进入后端容器执行
printenv查看环境变量值,或在NestJS的useFactory中打印uri确认连接字符串是否正确。 - 解决:确保部署平台已配置所有所需环境变量,或启用Docker Compose中的
env_file字段加载本地.env文件(注意部署时同步该文件到服务器)。
2. MongoDB初始化脚本未执行
- 挂载的
mongo-init.js可能因路径错误、权限问题,或数据卷已有旧数据(mongodbdata卷)导致脚本未执行,自定义用户未创建。 - 排查:查看MongoDB容器日志,搜索
docker-entrypoint-initdb.d相关内容确认脚本执行情况;进入MongoDB容器,用root用户登录后查看用户列表:mongo -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --authenticationDatabase admin use admin show users use ${DATABASE_NAME} show users - 解决:
- 确保
mongo-init.js路径正确,且部署时已同步到服务器对应目录; - 若数据卷存在旧数据,删除
mongodbdata卷后重启容器(注意备份数据); - 检查脚本语法,确保创建用户时指定了正确的
roles和authenticationDatabase。
- 确保
3. 连接字符串authSource配置错误
- 连接字符串指定
authSource=admin,但如果自定义用户是创建在目标数据库而非admin库,会导致认证失败。 - 排查:确认用户创建时的
authenticationDatabase参数,对应调整连接字符串的authSource。 - 解决:若用户在目标库创建,将
authSource改为目标库名称;若在admin库创建,确保用户拥有目标库的访问权限。
4. 网络解析异常(伪装成认证失败)
- 后端容器无法解析
${MONGODB_HOST}(如容器名在部署平台网络中无法识别),导致连接请求未正确到达MongoDB,返回类似认证失败的错误。 - 排查:在后端容器中ping
${MONGODB_HOST},或用mongosh "${MONGO_URI}"手动测试连接。 - 解决:确保
MONGODB_HOST设置为MongoDB容器的服务名(mongodb-dev),且两个容器在同一网络(my-network)中;若部署平台有特殊网络规则,调整网络配置确保容器间通信正常。
5. 密码特殊字符未编码
- 密码包含
@、:、/等特殊字符时,未进行URL编码会导致连接字符串解析错误,最终认证失败。 - 排查:打印生成的
MONGO_URI,检查密码部分是否正确编码(如@需替换为%40)。 - 解决:在环境变量中对密码进行URL编码,或在NestJS中用
encodeURIComponent()处理后拼接连接字符串:const encodedPass = encodeURIComponent(process.env.DATABASE_PASS); const uri = `mongodb://${process.env.DATABASE_USER}:${encodedPass}@${process.env.MONGODB_HOST}:27017/${process.env.DATABASE_NAME}?authSource=admin&directConnection=true`;
内容的提问来源于stack exchange,提问作者V.Sch
相关产品推荐
相关产品推荐

