如何在启动时为 MongoDB 容器创建数据库?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42912755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:55:50  来源:igfitidea点击:

How to create a DB for MongoDB container on start up?

mongodbdockerdocker-compose

提问by ReynierPM

I am working with Docker and I have a stack with PHP, MySQL, Apache and Redis. I need to add MongoDB now so I was checking the Dockerfilefor the latest version and also the docker-entrypoint.shfile from the MongoDB Dockerhubbut I couldn't find a way to setup a default DB, admin user/password and possibly auth method for the container from a docker-compose.ymlfile.

我正在使用 Docker,我有一个包含 PHP、MySQL、Apache 和 Redis 的堆栈。我需要添加的MongoDB,所以我现在是检查Dockerfile最新的版本,也将docker-entrypoint.sh从文件的MongoDB Dockerhub,但我无法找到一个方法来设置一个默认的数据库,管理员用户名/密码,并可能AUTH从docker-compose.yml文件中获取容器的方法。

In MySQL you can setup some ENV variables as for example:

在 MySQL 中,您可以设置一些 ENV 变量,例如:

db:
    image: mysql:5.7
    env_file: .env
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}

And this will setup the DB and the user/password as the rootpassword.

这将设置数据库和用户/密码作为root密码。

Is there any way to achieve the same with MongoDB? Anyone has some experience or workaround?

有什么办法可以用 MongoDB 实现相同的目标吗?任何人都有一些经验或解决方法?

回答by Matt

The official mongoimagehas merged a PR to include the functionalityto create users and databases at startup.

官方mongo图片已经合并公关,包括功能,在启动时创建用户和数据库。

The database initialisation will run when there is nothing populated in the /data/dbdirectory.

/data/db目录中没有填充任何内容时,将运行数据库初始化。

Admin User Setup

管理员用户设置

The environment variables to control "root" user setup are

控制“root”用户设置的环境变量是

  • MONGO_INITDB_ROOT_USERNAME
  • MONGO_INITDB_ROOT_PASSWORD
  • MONGO_INITDB_ROOT_USERNAME
  • MONGO_INITDB_ROOT_PASSWORD

Example

例子

docker run -d \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  mongod

You don't need to/can't use --authon the command line as the docker entrypoint.sh script adds this in when the environment variables exist.

您不需要/不能--auth在命令行上使用,因为 docker entrypoint.sh 脚本会在环境变量存在时添加它。

Database Initialisation

数据库初始化

The image also provides the /docker-entrypoint-initdb.d/path to deploy custom .jsor .shsetup scripts that will be run once on database initialisation. .jsscripts will be run against testby default or MONGO_INITDB_DATABASEif defined in the environment.

该映像还提供了/docker-entrypoint-initdb.d/部署自定义.js.sh安装脚本的路径,这些脚本将在数据库初始化时运行一次。.js脚本将在test默认情况下运行,或者MONGO_INITDB_DATABASE如果在环境中定义。

COPY mysetup.sh /docker-entrypoint-initdb.d/

or

或者

COPY mysetup.js /docker-entrypoint-initdb.d/

A simple initialisation javascript file that demonstrates logging and how to exit with an error (for result checking).

一个简单的初始化 javascript 文件,它演示了日志记录以及如何在出现错误时退出(用于结果检查)。

let error = true

let res = [
  db.container.drop(),
  db.container.drop(),
  db.container.createIndex({ myfield: 1 }, { unique: true }),
  db.container.createIndex({ thatfield: 1 }),
  db.container.createIndex({ thatfield: 1 }),
  db.container.insert({ myfield: 'hello', thatfield: 'testing' }),
  db.container.insert({ myfield: 'hello2', thatfield: 'testing' }),
  db.container.insert({ myfield: 'hello3', thatfield: 'testing' }),
  db.container.insert({ myfield: 'hello3', thatfield: 'testing' }),
]

printjson(res)

if (error) {
  print('Error, exiting')
  quit(1)
}

回答by Paul Wasilewski

Here another cleaner solution by using docker-composeand a jsscript.

这是使用docker-composejs脚本的另一个更清洁的解决方案。

This example assumes that both files (docker-compose.yml and mongo-init.js) lay in the same folder.

此示例假设两个文件(docker-compose.yml 和 mongo-init.js)位于同一文件夹中。

docker-compose.yml

docker-compose.yml

version: '3.7'

services:
    mongodb:
        image: mongo:latest
        container_name: mongodb
        restart: always
        environment:
            MONGO_INITDB_ROOT_USERNAME: <admin-user>
            MONGO_INITDB_ROOT_PASSWORD: <admin-password>
            MONGO_INITDB_DATABASE: <database to create>
        ports:
            - 27017:27017
        volumes:
            - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

mongo-init.js

mongo-init.js

db.createUser(
        {
            user: "<user for database which shall be created>",
            pwd: "<password of user>",
            roles: [
                {
                    role: "readWrite",
                    db: "<database to create>"
                }
            ]
        }
);

Then simply start the service by running the following docker-compose command

然后只需通过运行以下 docker-compose 命令来启动服务

docker-compose up --build -d mongodb 

回答by Mateusz Stefek

Here's a working solution that creates admin-useruser with a password, additional database (test-database), and test-userin that database.

这是一个有效的解决方案,它admin-user使用密码、附加数据库 ( test-database) 并test-user在该数据库中创建用户。

Dockerfile:

Dockerfile:

FROM mongo:4.0.3

ENV MONGO_INITDB_ROOT_USERNAME admin-user
ENV MONGO_INITDB_ROOT_PASSWORD admin-password
ENV MONGO_INITDB_DATABASE admin

ADD mongo-init.js /docker-entrypoint-initdb.d/

mongo-init.js:

mongo-init.js:

db.auth('admin-user', 'admin-password')

db = db.getSiblingDB('test-database')

db.createUser({
  user: 'test-user',
  pwd: 'test-password',
  roles: [
    {
      role: 'root',
      db: 'admin',
    },
  ],
});

The tricky part was to understand that *.js files were run unauthenticated. The solution authenticates the script as the admin-userin the admindatabase. MONGO_INITDB_DATABASE adminis essential, otherwise the script would be executed against the testdb. Check the source code of docker-entrypoint.sh.

棘手的部分是要了解 *.js 文件是在未经身份验证的情况下运行的。该解决方案验证脚本作为admin-useradmin数据库中。MONGO_INITDB_DATABASE admin是必不可少的,否则脚本将针对test数据库执行。检查docker-entrypoint.sh的源代码。

回答by x-yuri

Mongo image can be affected by MONGO_INITDB_DATABASEvariable, but it won't create the database. This variable determines current database when running /docker-entrypoint-initdb.d/*scripts. Since you can'tuse environment variables in scripts executed by Mongo, I went with a shell script:

Mongo 图像可以受MONGO_INITDB_DATABASE变量影响,但不会创建数据库。此变量确定运行/docker-entrypoint-initdb.d/*脚本时的当前数据库。由于您不能在 Mongo 执行的脚本中使用环境变量,我使用了一个 shell 脚本:

docker-swarm.yml:

docker-swarm.yml

version: '3.1'

secrets:
  mongo-root-passwd:
    file: mongo-root-passwd
  mongo-user-passwd:
    file: mongo-user-passwd

services:
  mongo:
    image: mongo:3.2
    environment:
      MONGO_INITDB_ROOT_USERNAME: $MONGO_ROOT_USER
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo-root-passwd
      MONGO_INITDB_USERNAME: $MONGO_USER
      MONGO_INITDB_PASSWORD_FILE: /run/secrets/mongo-user-passwd
      MONGO_INITDB_DATABASE: $MONGO_DB
    volumes:
      - ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh
    secrets:
      - mongo-root-passwd
      - mongo-user-passwd

init-mongo.sh:

init-mongo.sh

mongo -- "$MONGO_INITDB_DATABASE" <<EOF
    var rootUser = '$MONGO_INITDB_ROOT_USERNAME';
    var rootPassword = '$(cat "$MONGO_INITDB_ROOT_PASSWORD_FILE")';
    var admin = db.getSiblingDB('admin');
    admin.auth(rootUser, rootPassword);

    var user = '$MONGO_INITDB_USERNAME';
    var passwd = '$(cat "$MONGO_INITDB_PASSWORD_FILE")';
    db.createUser({user: user, pwd: passwd, roles: ["readWrite"]});
EOF

Alternatively, you can store init-mongo.shin configs (docker config create) and mount it with:

或者,您可以存储init-mongo.sh在 configs ( docker config create) 中并使用以下命令安装它:

configs:
    init-mongo.sh:
        external: true
...
services:
    mongo:
        ...
        configs:
            - source: init-mongo.sh
              target: /docker-entrypoint-initdb.d/init-mongo.sh

And secrets can be not stored in a file.

并且机密不能存储在文件中。

A coupleof gistson the matter.

对夫妇学家对此事。

回答by user2350644

In case someone is looking for how to configure MongoDB with authentication using docker-compose, here is a sample configuration using environment variables:

如果有人正在寻找如何使用身份验证配置 MongoDB docker-compose,这里是使用环境变量的示例配置:

version: "3.3"

services:

  db:
      image: mongo
      environment:
        - MONGO_INITDB_ROOT_USERNAME=admin
        - MONGO_INITDB_ROOT_PASSWORD=<YOUR_PASSWORD>
      ports:
        - "27017:27017"

When running docker-compose upyour mongo instance is run automatically with auth enabled. You will have a admin database with the given password.

运行docker-compose upmongo 实例时,会在启用身份验证的情况下自动运行。您将拥有一个带有给定密码的管理数据库。

回答by englishPete

If you are looking to remove usernames and passwords from your docker-compose.yml you can use Docker Secrets, here is how I have approached it.

如果您想从 docker-compose.yml 中删除用户名和密码,您可以使用Docker Secrets,这是我的方法。

version: '3.6'

services:
  db:
    image: mongo:3
    container_name: mycontainer
  secrets:
    - MONGO_INITDB_ROOT_USERNAME
    - MONGO_INITDB_ROOT_PASSWORD
  environment:
    - MONGO_INITDB_ROOT_USERNAME_FILE=/var/run/secrets/MONGO_INITDB_ROOT_USERNAME
    - MONGO_INITDB_ROOT_PASSWORD_FILE=/var/run/secrets/MONGO_INITDB_ROOT_PASSWORD
secrets:
  MONGO_INITDB_ROOT_USERNAME:
    file:  secrets/${NODE_ENV}_mongo_root_username.txt
  MONGO_INITDB_ROOT_PASSWORD:
    file:  secrets/${NODE_ENV}_mongo_root_password.txt

I have use the file:option for my secrets however, you can also use external:and use the secrets in a swarm.

我已经为我的秘密使用了file:选项,但是你也可以使用external:并在一个群体中使用这些秘密。

The secrets are available to any script in the container at /var/run/secrets

机密可用于 /var/run/secrets 容器中的任何脚本

The Docker documentation has this to say about storing sensitive data...

Docker 文档有关于存储敏感数据的说法......

https://docs.docker.com/engine/swarm/secrets/

https://docs.docker.com/engine/swarm/secrets/

You can use secrets to manage any sensitive data which a container needs at runtime but you don't want to store in the image or in source control, such as:

您可以使用机密来管理容器在运行时需要的任何敏感数据,但您不想存储在图像或源代码控制中,例如:

Usernames and passwords TLS certificates and keys SSH keys Other important data such as the name of a database or internal server Generic strings or binary content (up to 500 kb in size)

用户名和密码 TLS 证书和密钥 SSH 密钥 其他重要数据,例如数据库或内部服务器的名称 通用字符串或二进制内容(最大 500 kb)