如何使用 docker-compose 在 mongodb 中创建用户

How to create user in mongodb with docker-compose

我正在尝试创建某种类型的脚本,该脚本将使用 mongodb 创建一个 docker 并自动创建一个用户。

我通常可以使用 docker-compose 管理我的 docker 图片,但这次,我不知道该怎么做。

基本上,这是我必须做的:

  1. clean/destroy 容器 (docker-compose down)
  2. 使用 mongodb 创建一个 docker 容器并启动它(没有 --auth parameter
  3. 执行包含db.createUser()
  4. 的java脚本
  5. 停止容器
  6. 使用 --auth 参数重新启动同一个容器,以允许使用在 java 脚本
  7. 中创建的用户登录

我找不到如何使用 docker-compose 正确地做到这一点,因为当它启动时,我必须给它命令 --auth。如果这样做,我将无法执行我的 java 脚本来添加我的用户。 MongoDB 如果没有用户且未提供 --auth 参数,则允许在不登录的情况下创建用户。

我想自动执行,我不想手动执行某些命令。目标是拥有一个可以在每次集成测试之前执行的脚本,以从干净的数据库开始。

这是我的项目:

integration-test/src/test/resources/scripts/docker-compose.yml

mongodb:
    container_name: mongo
    image: mongo
  ports:
    - "27017:27017"
  volumes:
    - .:/setup
  command: --auth

integration-test/src/test/resources/scripts/docker-init.sh

docker-compose down
docker-compose up -d
sleep 1
docker exec mongo bash -c "mongo myDatabase /setup/mongodb-setup.js"

integration-test/src/test/resources/scripts/mongodb-setup.js

db.createUser(
{
    user: "myUser",
    pwd: "myPassword",
    roles: [
      { role: "readWrite", db: "myDatabase" }
    ]
})

找到一种使用新参数重新启动容器的方法(在本例中为 --auth)会有所帮助,但我找不到该怎么做(docker 启动不带参数).

知道我应该怎么做吗?

如果没有,我仍然可以使用一些 Java 代码或其他东西从我的数据库中删除所有内容,但我想要一个完整的 mongodb docker 使用脚本创建的设置。

编辑: tutumcloud 存储库已弃用且不再维护,请参阅其他答案

我建议你使用环境变量来设置mongo用户、数据库和密码。 tutum(拥有者Docker)发布了一张非常好的图片

https://github.com/tutumcloud/mongodb

docker run -d -p 27017:27017 -p 28017:28017 -e MONGODB_USER="user" -e MONGODB_DATABASE="mydatabase" -e MONGODB_PASS="mypass" tutum/mongodb

您可以将这些变量转换为 docker-compose 环境变量。您不必对其进行硬编码。

environment:
    MONGODB_USER: "${db_user_env}"
    MONGODB_DATABASE: "${dbname_env}"
    MONGODB_PASS: "${db_pass}"

此配置将从您会话的环境变量中读取。

向 mongo 命令添加 --noauth 选项

从我的 docker-compose.yml 文件中提取

mongors:
  image: mongo:latest
  command: mongod --noprealloc --smallfiles --replSet mongors2 --dbpath /data/db --nojournal --oplogSize 16 --noauth
  environment:
    TERM: xterm
  volumes:
    - ./data/mongors:/data/db

阅读官方mongo docker page后,我发现即使使用了 auth 选项,您也可以一次性创建一个管理员用户。这没有很好的记录,但它确实有效(希望它不是一个功能)。 因此,您可以一直使用 auth 选项。

我创建了一个 github 存储库,其中包含包含要使用的命令的脚本。 运行 最重要的命令行是:

docker exec db_mongodb mongo admin /setup/create-admin.js
docker exec db_mongodb mongo admin /setup/create-user.js -u admin -p admin --authenticationDatabase admin

第一行将创建管理员用户(并且 mongo 即使使用 auth 选项也不会抱怨)。第二行将创建您的 "normal" 用户,使用第一行的管理员权限。

我就是这样做的,我的要求是与 mongodb 一起启动一些容器,其他容器希望用户在出现时在场,这对我有用。好的部分是,mongoClientTemp 在命令执行后退出,因此容器不会停留。

version: '2'
services:
  mongo:
   image: mongo:latest
   container_name: mongo
   ports:
    - "27017:27017"
   volumes:
    - /app/hdp/mongo/data:/data/db

  mongoClientTemp:
   image: mongo:latest
   container_name: mongoClientTemp
   links:
    - mongo:mongo
   command: mongo --host mongo --eval  "db.getSiblingDB('dashboard').createUser({user:'db', pwd:'dbpass', roles:[{role:'readWrite',db:'dashboard'}]});"
   depends_on:
    - mongo

  another-container:
   image: another-image:v01
   container_name: another-container
   ports:
    - "8080:8080"
   volumes:
    - ./logs:/app/logs
   environment:
    - MONGODB_HOST=mongo
    - MONGODB_PORT=27017
   links:
    - mongo:mongo
   depends_on:
    - mongoClientTemp

官方 mongo 镜像现在支持以下环境变量,可以在 docker-compose 中使用,如下所示:

environment:
      - MONGO_INITDB_ROOT_USERNAME=user
      - MONGO_INITDB_ROOT_PASSWORD=password
      - MONGO_INITDB_DATABASE=test

更多解释请见:

文件:docker-compose.yaml

mongo:
    image: mongo:latest
    volumes_from:
        - data
    ports:
        - "27017:27017"
    command: --auth

    container_name: "db_mongodb"

data:
    image: mongo:latest
    volumes:
        - /var/lib/mongo
        - ./setup:/setup
    command: "true"
    container_name: "db_mongodb_data"

文件:.buildMongo.sh

#!/bin/sh
docker-compose down
docker-compose up -d
sleep 1
docker exec db_mongodb  mongo admin /setup/create-admin.js
docker exec db_mongodb  mongo myDb /setup/create-user.js -u admin -p admin --authenticationDatabase admin

create-admin.js 和 create-user.js 文件是您使用 mongo shell 使用的命令。因此,它们必须易于您理解。真正的方向就像jzqa的回答,"environment variables"。 所以这里的问题是如何创建用户。我认为这至少回答了这一点,您可以在此处查看完整设置 https://github.com/Lus1t4nUm/mongo_docker_bootstrap

Mongo 图像提供 /docker-entrypoint-initdb.d/ 路径来部署自定义 .js 或 .sh 安装脚本。

检查此 post 以获取更多详细信息:

为了初始化mongo,使用初始用户-密码-数据库三元组和initdb脚本,只有一个docker-compose.yml,无需任何额外配置,您可以使用bitnami/mongo 图片。

就我而言,我没有 运行 我的脚本位于 /docker-入口点-initdb.d 设置环境变量后容器中的目录; MONGODB_USERNAMEMONGODB_PASSWORD(bitnami 图像的特定环境变量)因为 mongod 运行s 与 --auth 选项自动当你设置这些变量。因此,当容器正在执行脚本时,我遇到了身份验证错误。

因为,它正在连接到:mongodb://192.168.192.2:27017/compressors=disabled&gssapiServiceName=mongodb

TERMINAL LOG OF THE ERROR

第一个 DOCKER-撰写文件:

version: "3"
services:
mongodb:
    container_name: mongodb
    image: 'docker.io/bitnami/mongodb:4.2-debian-10'
    ports:
        - "27017:27017"
    volumes:
        - "mongodb_data:/bitnami/mongodb"
        - "./mongodb/scripts:/docker-entrypoint-initdb.d"
    environment:
        - MONGODB_INITSCRIPTS_DIR=/docker-entrypoint-initdb.d
        - MONGODB_USERNAME=some_username
        - MONGODB_PASSWORD=some_password
        - MONGODB_DATABASE=some_db_name
    networks:
        backend:
    restart: unless-stopped
volumes:
    mongodb_data:
networks:
    backend:
        driver: bridge

在 ./mongodb/scripts 路径下初始化 JS 文件:

let db = connect("localhost:27017/some_db_name");
db.auth("some_username", "some_password");
let collections = db.getCollectionNames();
let storeFound = false; 
let index;
for(index=0; index<collections.length; index++){
   if ("store" === collections[index]){
       storeFound = true;   
   }
}
if(!storeFound ){
   db.createCollection("store");
   db.store.createIndex({"name": 1});
}

因此,我决定在检查 https://github.com/bitnami/bitnami-docker-mongodb/blob/master/4.2/debian-10/rootfs/opt/bitnami/scripts/libmongodb.sh 文件后向我的 docker-compose.yml 添加新的环境变量。

在这个sh文件中,有类似mongodb_custom_init_scripts()的函数来执行脚本。为了执行所有脚本文件,它 运行s mongodb_execute() 方法。在此方法中,在 mongod 实例启动且 运行 之后,mongo 客户端使用一些参数连接到 mongod 实例。

########################
# Execute an arbitrary query/queries against the running MongoDB service
# Stdin:
#   Query/queries to execute
# Arguments:
#    - User to run queries
#    - Password
#    - Database where to run the queries
#    - Host (default to result of get_mongo_hostname function)
#    - Port (default $MONGODB_PORT_NUMBER)
#    - Extra arguments (default $MONGODB_CLIENT_EXTRA_FLAGS)
# Returns:
#   None
########################
mongodb_execute() {
    local -r user="${1:-}"
    local -r password="${2:-}"
    local -r database="${3:-}"
    local -r host="${4:-$(get_mongo_hostname)}"
    local -r port="${5:-$MONGODB_PORT_NUMBER}"
    local -r extra_args="${6:-$MONGODB_CLIENT_EXTRA_FLAGS}"
    local result
    local final_user="$user"
    # If password is empty it means no auth, do not specify user
    [[ -z "$password" ]] && final_user=""

    local -a args=("--host" "$host" "--port" "$port")
    [[ -n "$final_user" ]] && args+=("-u" "$final_user")
    [[ -n "$password" ]] && args+=("-p" "$password")
    [[ -n "$extra_args" ]] && args+=($extra_args)
    [[ -n "$database" ]] && args+=("$database")

    "$MONGODB_BIN_DIR/mongo" "${args[@]}"
}

之后,我向 docker-compose 添加了新的环境变量,例如 MONGODB_ADVERTISED_HOSTNAMEMONGODB_PORT_NUMBER,并且,MONGODB_CLIENT_EXTRA_FLAGS

所以我的最终 docker-compose.yml 看起来像:

version: "3"
services:
mongodb:
    container_name: mongodb
    image: 'docker.io/bitnami/mongodb:4.2-debian-10'
    ports:
        - "27017:27017"
    volumes:
        - "mongodb_data:/bitnami/mongodb"
        - "./mongodb/scripts:/docker-entrypoint-initdb.d"
    environment:
        - MONGODB_INITSCRIPTS_DIR=/docker-entrypoint-initdb.d
        - MONGODB_USERNAME=some_username
        - MONGODB_PASSWORD=some_password
        - MONGODB_DATABASE=some_db_name
        - MONGODB_ADVERTISED_HOSTNAME=localhost
        - MONGODB_PORT_NUMBER=27017
        - MONGODB_CLIENT_EXTRA_FLAGS=--authenticationDatabase=some_db_name
    networks:
        backend:
    restart: unless-stopped
volumes:
    mongodb_data:
networks:
    backend:
        driver: bridge

现在是通过这个连接的url:

mongodb://localhost:27017/?authSource=some_db_name&compressors=disabled &gssapiServiceName=mongodb

在你的项目目录中创建另一个目录docker-entrypoint-initdb.d 然后 文件树如下所示:

Project-directory
 ┣ docker-entrypoint-initdb.d
 ┃ ┗ mongo-init.js
 ┗ docker-compose.yaml

docker-compose.yml包含:

version: "3.7"
services:
  mongo:
    container_name: container-mongodb
    image: mongo:latest
    restart: always
    ports:
      - 27017:27017

    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: root-db

    volumes:
      - ./docker-entrypoint-initdb.d/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

mongo-init.js 包含 javascript 代码以创建具有不同角色的用户。

print("Started Adding the Users.");
db = db.getSiblingDB("admin");
db.createUser({
  user: "userx",
  pwd: "1234",
  roles: [{ role: "readWrite", db: "admin" }],
});
print("End Adding the User Roles.");

您可以根据需要修改mongo-init.js