Docker Compose中my-service连接MongoDB容器认证失败求助
1. 检查MongoDB初始化是否生效
MongoDB的MONGO_INITDB_ROOT_USERNAME和MONGO_INITDB_ROOT_PASSWORD仅在第一次启动且数据卷为空时才会创建root用户。如果之前已经创建过db_vol卷,卷内可能残留无认证或密码不匹配的旧数据,导致新的初始化参数无法生效。
解决方法:
- 停止并删除现有容器及关联卷:
docker-compose down -v - 重新启动服务:
docker-compose up -d
2. 简化my-service的环境变量配置
你的docker-compose.yml中,my-service同时配置了env_file和environment字段,这种冗余配置容易引发变量加载优先级问题:environment中的变量是从Docker Compose所在环境(根目录.env或宿主环境)解析的,即便两个.env内容一致,也可能导致变量传递异常。
建议移除environment字段,仅保留env_file让容器直接加载my-service/.env的变量:
services: my-service: depends_on: - mongodb env_file: ./my-service/.env container_name: my-service build: ./my-service ports: - "3002:3002"
3. 确保连接URI正确指定认证源
root用户是在admin数据库下创建的,连接时必须明确指定authSource=admin,否则MongoDB会尝试用你指定的DB_NAME(my_db)进行认证,而该数据库下不存在root用户。
修正连接URI:
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`
4. 处理MongoDB启动就绪延迟问题
depends_on仅保证容器启动顺序,不保证MongoDB服务完全就绪。my-service可能在MongoDB初始化完成前发起连接,导致认证失败。
解决方法:在数据库连接逻辑中添加重试机制:
async function connectDB() { let retries = 5; while (retries > 0) { try { await mongoose.connect(dbUri, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }); console.log("Database connected successfully"); break; } catch (err) { retries--; console.log(`Connection failed, retries left: ${retries}`); await new Promise(resolve => setTimeout(resolve, 2000)); } } }
5. 验证环境变量是否正确传递
进入my-service容器,检查环境变量是否加载正常:
docker exec -it my-service sh echo $DB_USER echo $DB_PASSWORD echo $DB_HOST
如果输出为空或不符合预期,需检查docker-compose.yml中env_file的路径是否正确(路径是相对docker-compose.yml文件的位置)。
内容的提问来源于stack exchange,提问作者user842225

