简体   繁体   English

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

[英]How to create user in mongodb with docker-compose

I'm trying to create some kind of script that will create a docker with mongodb and automatically create a user.我正在尝试创建某种脚本,该脚本将使用 mongodb 创建一个 docker 并自动创建一个用户。

I can usually manage my docker images with docker-compose but this time, I don't know how to do it.我通常可以使用 docker-compose 管理我的 docker 镜像,但这次,我不知道该怎么做。

Basically, here is what I have to do:基本上,这是我必须做的:

  1. clean/destroy container ( docker-compose down )清理/销毁容器( docker-compose down
  2. create a docker container with mongodb and start it (without --auth parameter )使用 mongodb 创建一个--auth parameter容器并启动它(不带--auth parameter
  3. execute a java script containing db.createUser()执行包含db.createUser()的 java 脚本
  4. stop the container停止容器
  5. restart the same container with --auth parameter to allow login with the user created in the javascript使用--auth参数重新启动同一个容器以允许使用在 javascript 中创建的用户登录

I can't find how to do that properly with docker-compose because when it starts, I have to give it the command --auth.我无法找到如何使用 docker-compose 正确执行此操作,因为当它启动时,我必须给它命令 --auth。 If I do that, I cannot execute my javascript to add my user.如果我这样做,我将无法执行我的 javascript 来添加我的用户。 MongoDB allows users creation without being logged in if there is no user and if --auth parameter is not provided.如果没有用户且未提供 --auth 参数,MongoDB 允许用户在未登录的情况下创建。

I want to do that automatically, I do not want to manually do some commands.我想自动执行此操作,我不想手动执行某些命令。 The goal is to have a script that can be executed before each integration tests to start from a clean database.目标是拥有一个可以在每次集成测试之前执行的脚本,以从干净的数据库开始。

Here is my project:这是我的项目:

integration-test/src/test/resources/scripts/docker-compose.yml集成测试/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集成测试/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集成测试/src/test/resources/scripts/mongodb-setup.js

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

Finding a way to start again a container with a new parameter (in this case --auth ) would help but I can't find how to do that (docker start does not take parameters).找到一种使用新参数(在本例中为--auth )重新启动容器的方法会有所帮助,但我找不到如何做到这一点(docker start 不接受参数)。

Any idea how I should do what I would like ?知道我应该如何做我想做的吗?

If not, I can still delete everything from my database with some Java code or something else but I would like a complete mongodb docker setup created with a script.如果没有,我仍然可以使用一些 Java 代码或其他代码从我的数据库中删除所有内容,但我想要一个使用脚本创建的完整 mongodb docker 设置。

The official mongo image now supports following environment variables that can be used in docker-compose as below:官方 mongo 镜像现在支持以下可以在 docker-compose 中使用的环境变量,如下所示:

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

more explanation at: https://stackoverflow.com/a/42917632/1069610更多解释: https : //stackoverflow.com/a/42917632/1069610

This is how I do it, my requirement was to bring up a few containers along with mongodb, the other containers expect a user to be present when they come up, this worked for me.我就是这样做的,我的要求是随 mongodb 一起启动一些容器,其他容器希望用户在出现时出现,这对我有用。 The good part is, the mongoClientTemp exits after the command is executed so the container doesn't stick around.好的部分是, 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

EDIT: tutumcloud repository is deprecated and no longer maintained, see other answers编辑: tutumcloud 存储库已弃用且不再维护,请参阅其他答案

I suggest that you use environment variables to set mongo user, database and password.我建议你使用环境变量来设置 mongo 用户、数据库和密码。 tutum (owned by Docker) published a very good image tutum (由Docker拥有)发布了一个非常好的镜像

https://github.com/tutumcloud/mongodb 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

You may convert these variables into docker-compose environments variables.您可以将这些变量转换为 docker-compose 环境变量。 You don't have to hard code it.您不必对其进行硬编码。

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

This configuration will read from your session's environment variables.此配置将从会话的环境变量中读取。

After reading the the official mongo docker page , I've found that you can create an admin user one single time, even if the auth option is being used.阅读官方mongo docker 页面后,我发现即使使用了 auth 选项,您也可以一次性创建一个管理员用户。 This is not well documented, but it simply works (hope it is not a feature).这没有很好的文档记录,但它只是有效(希望它不是一个功能)。 Therefore, you can keep using the auth option all the time.因此,您可以一直使用 auth 选项。

I created a github repository with scripts wrapping up the commands to be used.我创建了一个github存储库,其中包含包含要使用的命令的脚本。 The most important command lines to run are:要运行的最重要的命令行是:

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

The first line will create the admin user (and mongo will not complain even with auth option).第一行将创建管理员用户(即使使用 auth 选项,mongo 也不会抱怨)。 The second line will create your "normal" user, using the admin rights from the first one.第二行将使用第一行的管理员权限创建您的“普通”用户。

Mongo image provides the /docker-entrypoint-initdb.d/ path to deploy custom .js or .sh setup scripts. Mongo 镜像提供了 /docker-entrypoint-initdb.d/ 路径来部署自定义 .js 或 .sh 安装脚本。

Check this post to get more details : How to create a DB for MongoDB container on start up?查看这篇文章以获取更多详细信息: 如何在启动时为 MongoDB 容器创建数据库?

file: docker-compose.yaml文件: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"

file: .buildMongo.sh文件:.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

The create-admin.js and create-user.js files are commands that you use using the mongo shell. create-admin.js 和 create-user.js 文件是您使用 mongo shell 使用的命令。 So they must be easy for you to understand.因此,它们必须易于您理解。 The real direction is like the jzqa answer, "environment variables".真正的方向就像jzqa的回答,“环境变量”。 So the question here is how to create a user.所以这里的问题是如何创建用户。 I think this answers that point at least, you can check the complete setup here https://github.com/Lus1t4nUm/mongo_docker_bootstrap我认为这至少回答了这一点,您可以在此处查看完整的设置https://github.com/Lus1t4nUm/mongo_docker_bootstrap

For initializing mongo with initial user-password-db triple and initdb scripts with only one docker-compose.yml, without any extra configuration, you can use bitnami/mongo image.使用初始用户-密码-db 三元组初始化 mongo 和仅使用一个 docker-compose.yml 的 initdb 脚本初始化 mongo,无需任何额外配置,您可以使用 bitnami/mongo 镜像。

In my case, I didn't run my scripts under /docker-entrypoint-initdb.d directory in the container after setting environment variables;就我而言,我没有在设置环境变量后在容器中的/docker-entrypoint-initdb.d目录下运行我的脚本; MONGODB_USERNAME and MONGODB_PASSWORD (specific env variables for bitnami image) because mongod runs with --auth option automatically when you set these variables. MONGODB_USERNAMEMONGODB_PASSWORD (bitnami 图像的特定环境变量),因为当您设置这些变量时, mongod 会自动使用--auth选项运行。 Consequently, I got authentication errors when the container was in the process of executing the scripts.因此,当容器正在执行脚本时,我遇到了身份验证错误。

Because, it was connecting to: mongodb://192.168.192.2:27017/compressors=disabled&gssapiServiceName=mongodb因为,它连接到: mongodb://192.168.192.2:27017/compressors=disabled&gssapiServiceName=mongodb

TERMINAL LOG OF THE ERROR错误的终端日志

FIRST DOCKER-COMPOSE FILE:第一个 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

INIT JS FILE UNDER ./mongodb/scripts PATH:在 ./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});
}

So, I decided to add new environment variables to my docker-compose.yml after inspecting https://github.com/bitnami/bitnami-docker-mongodb/blob/master/4.2/debian-10/rootfs/opt/bitnami/scripts/libmongodb.sh file.因此,我决定在检查https://github.com/bitnami/bitnami-docker-mongodb/blob/master/4.2/debian-10/rootfs/opt/bitnami/后向我的 docker-compose.yml 添加新的环境变量脚本/libmongodb.sh文件。

In this sh file, there is function like mongodb_custom_init_scripts() for executing the scripts.在这个 sh 文件中,有像mongodb_custom_init_scripts()这样的函数来执行脚本。 For executing all script files, it runs mongodb_execute() method.为了执行所有脚本文件,它运行mongodb_execute()方法。 In this method, after mongod instance is up and run, mongo client is connecting to the mongod instance by using some parameters.在该方法中,mongod 实例启动并运行后,mongo 客户端通过使用一些参数连接到 mongod 实例。

########################
# Execute an arbitrary query/queries against the running MongoDB service
# Stdin:
#   Query/queries to execute
# Arguments:
#   $1 - User to run queries
#   $2 - Password
#   $3 - Database where to run the queries
#   $4 - Host (default to result of get_mongo_hostname function)
#   $5 - Port (default $MONGODB_PORT_NUMBER)
#   $6 - 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[@]}"
}

After that I added new environment variables to my docker-compose like MONGODB_ADVERTISED_HOSTNAME , MONGODB_PORT_NUMBER , and, MONGODB_CLIENT_EXTRA_FLAGS之后,我向我的docker -compose 添加了新的环境变量,例如MONGODB_ADVERTISED_HOSTNAMEMONGODB_PORT_NUMBERMONGODB_CLIENT_EXTRA_FLAGS

So my final docker-compose.yml looks like:所以我最终的 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

Now, it was connecting by this url:现在,它通过这个 url 连接:

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

In your project directory create another directory docker-entrypoint-initdb.d then the file tree looks like this:在您的项目目录中创建另一个目录docker-entrypoint-initdb.d然后文件树如下所示:

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

The docker-compose.yml contains: 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 contains the javascript code to create user with different roles. 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.");

You can modify the mongo-init.js as you need.您可以根据需要修改mongo-init.js

add --noauth option to the mongo command在 mongo 命令中添加 --noauth 选项

extract from my docker-compose.yml file从我的 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

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

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