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

157
我正在使用Docker,我的堆栈包括PHP、MySQL、Apache和Redis。现在我需要添加MongoDB,因此我正在检查最新版本的Dockerfile以及MongoDB Dockerhub上的docker-entrypoint.sh文件,但我无法找到一种方法来设置默认的数据库、管理员用户/密码和可能的授权方法,以便从docker-compose.yml文件中为容器进行设置。
在MySQL中,您可以设置一些环境变量,例如:
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}

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

有没有办法在MongoDB中实现相同的功能?有人有经验或解决方法吗?


你能否创建一个基于MySQL的容器,并按照你的要求进行设置,然后使用它? - Valentin
@Valentin 当然我可以,但你的观点是什么? - ReynierPM
我的意思是,您可以在Dockerfile中使用变量设置默认的DB、管理员用户名/密码和可能的身份验证方法,然后将它们传递到compose文件中。 - Valentin
注意:如果使用任何使用mongo-init脚本的解决方案,请确保为依赖于mongo的容器设置restart: unless-stopped(或除no之外的其他内容)。这是因为这些容器在初始化时第一次连接mongo时将失败(即使有depends_on标志)。请参阅此线程以获取详细信息https://dev59.com/oVwZ5IYBdhLWcg3wLdyz#35170810 - java-addict301
14个回答

3

我的回答基于@x-yuri提供的回答;但是我的情况有点不同。我想要一个包含脚本的镜像,而不需要绑定挂载它。

mongo-init.sh - 不知道是否需要,但我也运行了chmod +x mongo-init.sh

#!/bin/bash
# https://dev59.com/R1gQ5IYBdhLWcg3wWCnP#53522699
# https://dev59.com/qloU5IYBdhLWcg3wHERo#37811764
mongo -- "$MONGO_INITDB_DATABASE" <<EOF
  var rootUser = '$MONGO_INITDB_ROOT_USERNAME';
  var rootPassword = '$MONGO_INITDB_ROOT_PASSWORD';
  var user = '$MONGO_INITDB_USERNAME';
  var passwd = '$MONGO_INITDB_PASSWORD';

  var admin = db.getSiblingDB('admin');

  admin.auth(rootUser, rootPassword);
  db.createUser({
    user: user,
    pwd: passwd,
    roles: [
      {
        role: "root",
        db: "admin"
      }
    ]
  });
EOF

Dockerfile

FROM mongo:3.6

COPY mongo-init.sh /docker-entrypoint-initdb.d/mongo-init.sh

CMD [ "/docker-entrypoint-initdb.d/mongo-init.sh" ]

docker-compose.yml:

version: '3'

services:
    mongodb:
        build: .
        container_name: mongodb-test
        environment:
            - MONGO_INITDB_ROOT_USERNAME=root
            - MONGO_INITDB_ROOT_PASSWORD=example
            - MONGO_INITDB_USERNAME=myproject
            - MONGO_INITDB_PASSWORD=myproject
            - MONGO_INITDB_DATABASE=myproject

    myproject:
        image: myuser/myimage
        restart: on-failure
        container_name: myproject
        environment:
            - DB_URI=mongodb
            - DB_HOST=mongodb-test
            - DB_NAME=myproject
            - DB_USERNAME=myproject
            - DB_PASSWORD=myproject
            - DB_OPTIONS=
            - DB_PORT=27017            
        ports:
            - "80:80"

在那之后,我继续将这个Dockerfile发布为一个镜像以在其他项目中使用。

注意:如果没有添加CMD,mongo会抛出一个“未绑定变量错误”。


2

docker-compose.yml

version: '3.9'

services:
  mongodb:
    image: mongo
    container_name: chat_history
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
      MONGO_INITDB_DATABASE: ${MONGO_INITDB_DATABASE}
    ports:
      - "${MONGO_INITDB_PORT}:27017"
    env_file:
      - .env
    volumes:
      - ./data/mongo:/data/db
      - ./scripts/docker/mongo/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

mongo-init.js

db = db.getSiblingDB('admin');
db.auth(
    process.env.MONGO_INITDB_ROOT_USERNAME,
    process.env.MONGO_INITDB_ROOT_PASSWORD,
);

db = db.getSiblingDB(process.env.MONGO_INITDB_DATABASE);
db.createUser({
    user: process.env.MONGO_USER,
    pwd: process.env.MONGO_PASSWORD,
    roles: [{
        role: 'readWrite',
        db: process.env.MONGO_INITDB_DATABASE,
    }]
});

db.createCollection(process.env.MAIN_DB_COLLECTION);

首先,我已经授权了'admin'用户,然后我创建了一个新表格,以便我可以直接从应用程序(Go)连接到它。


2

在没有root访问权限的情况下,在MongoDB docker容器中创建多个数据库和用户的步骤。

  1. Stop docker-compose with
    docker-compose down
    
    command, or 'docker-compose -f docker-compose.yml -f docker-compose.dev.yml <...>' if you have multiple files.
  2. Remove volumes assigned to the mongo container. Run 'docker volume ls'. If there is anything similar to <projectfolder>_mongodb--vol, remove it by applying
    docker volume rm <projectfolder>_mongodb--vol
    
  3. Set up folder with .js or .sh mongo database init scripts. For example, mongo-init/db_1.js:
    conn = new Mongo();
    db = conn.getDB("db_1")
    db.createUser(
    {
        user: "db_1_service_user",
        pwd: "<password>",
        roles: [
            {
                role: "readWrite",
                db: "db_1"
            }
        ]
    }
    );
    
    Repeat the procedure for mongo-init/db_2.js file. conn.getDB() creates the database, db.createUser() creates a user and assigns it to the database.
  4. docker-compose.yml fragment, notice the mount binding from ./mongo-init/ local folder containing database init scripts to the remote /docker-entrypoint-initdb.d/:
    version: "3.8"
    services:
    
      my-service_1:
        depends_on:
          - mongodb
    
      my-service_2:
        depends_on:
          - mongodb
    
      mongodb:
        image: mongo:4.4-bionic
        ports:
        - "27017:27017"
        volumes:
        - mongodb--vol:/data/db
        - ./mongo-init/:/docker-entrypoint-initdb.d/:ro
        healthcheck:
        test: "echo 'db.runCommand(\"ping\").ok'"
        interval: 5s
        timeout: 5s
        retries: 3
    
    # in-service volumes are very slow in MacOS and Windows, 
    # so using fast shared volumes for large storage
    volumes:
        mongodb--vol:
    
  5. Apply connection strings to your applications:
    mongodb://db_1_service_user:<password>@mongodb:27017/db_1
    
    mongodb://db_2_service_user:<password>@mongodb:27017/db_2
    

1
如果您正在使用docker-compose,并且在创建卷后尝试运行任何这些建议,则可能需要删除该卷,因为如果卷已经存在,则初始化脚本将无法运行。要查看是否是这种情况,请尝试运行:
docker volume ls
如果您的mongo数据在那里,您应该在一个名为类似于_的卷中看到它。
如果卷类似于db_volume,您将需要运行:
docker volume rm db_volume

你可能需要清空容器才能让这个操作生效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接