问题描述
正在尝试创建一个包含MongoDB的自定义容器(因此不使用官方的MongoDB容器)。他想要为数据库添加身份验证,并且在持久化身份验证数据方面遇到了问题。在Dockerfile中,他在某个时刻运行了以下命令:
RUN (nohup mongod &) && mongo < /data/mongo.js
而mongo.js
文件内容如下:
use admindb.createUser( { user: "admin", pwd: "abcd", roles: [ "root" ] })
在构建过程中,上述命令输出如下:
Successfully added user: { "user" : "admin", "roles" : [ "root" ] }Removing intermediate container...
但是,在构建完成后,当用户登录到容器并使用--auth
标志启动Mongo时,仍然无法登录:
# mongo -u admin -p abcd --authenticationDatabase "admin"
MongoDB shell version: 3.2.11
Enter password: connecting to: abcd
exception: login failed
请问缺少了什么?
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
在构建自定义容器时,您可以通过将身份验证信息作为环境变量传递给官方镜像来简化操作。您可以使用类似以下的Compose文件:
version: '3.1'
services:
mongo:
image: mongo
restart: always
container_name: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: abcd
ports:
- "27017:27017"
volumes:
- ./databases:/data/db
mongo-express:
image: mongo-express
restart: always
container_name: mongo-express
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: abcd
上述Compose文件中,我们定义了两个服务 mongo
和 mongo-express
。在 mongo
服务中,我们通过 environment
属性指定了 MONGO_INITDB_ROOT_USERNAME
和 MONGO_INITDB_ROOT_PASSWORD
环境变量,这将在容器启动时自动创建具有指定用户名和密码的管理员用户。此外,我们还将 ./databases
目录挂载到容器的 /data/db
目录,以便持久化数据库文件。
在 mongo-express
服务中,我们通过 environment
属性指定了 ME_CONFIG_MONGODB_ADMINUSERNAME
和 ME_CONFIG_MONGODB_ADMINPASSWORD
环境变量,这将在容器启动时自动配置Mongo Express以连接到MongoDB。
通过使用上述Compose文件,您可以轻松地创建一个包含MongoDB和Mongo Express的容器,并在构建过程中自动创建管理员用户。此外,您的数据库文件也将持久化保存在本地的 ./databases
目录中。
方案2
使用脚本或工具来管理容器的启动顺序可能会增加复杂性,并且需要确保容器A和容器B之间的依赖关系正确设置。
另一种方法是编写脚本或使用工具来控制容器的运行顺序。您可以使用docker run
命令来手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。
示例:
以下是一个简单的bash脚本示例,可以在容器A启动后启动容器B:
#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b
在这个示例中,我们首先使用docker run
命令启动容器A,并将其命名为container_a
。然后,使用一个循环来等待容器A完全启动(这里是通过在容器内运行echo
命令来测试)。一旦容器A就绪,我们再使用docker run
命令启动容器B,并将其命名为container_b
。
以上是两种解决方案,您可以根据自己的需求选择适合的方法来持久化数据。希望对您有帮助!