web-dev-qa-db-fra.com

Comment créer une base de données pour le conteneur MongoDB au démarrage?

Je travaille avec Docker et j'ai une pile avec PHP, MySQL, Apache et Redis. Je dois maintenant ajouter MongoDB pour vérifier le fichier Dockerfile et la version la plus récente le fichier docker-entrypoint.sh du fichier MongoDB Dockerhub mais je ne pouvais pas trouver un moyen de configurer une base de données, un utilisateur/mot de passe administrateur par défaut et éventuellement une méthode auth pour le conteneur à partir d'un docker-compose.yml fichier.

Dans MySQL, vous pouvez configurer certaines variables ENV, comme par exemple:

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}

Et cela configurera la base de données et le nom d'utilisateur/mot de passe en tant que mot de passe root.

Existe-t-il un moyen d'obtenir le même résultat avec MongoDB? Quelqu'un a une expérience ou une solution de contournement?

30
ReynierPM

Le officiel mongo image a a fusionné un PR pour inclure la fonctionnalité afin de créer des utilisateurs et des bases de données au démarrage.

L’initialisation de la base de données s’exécutera s’il n’ya rien renseigné dans le fichier /data/db répertoire.

Configuration utilisateur administrateur

Les variables d’environnement permettant de contrôler la configuration utilisateur "root" sont les suivantes:

  • MONGO_INITDB_ROOT_USERNAME
  • MONGO_INITDB_ROOT_PASSWORD

Exemple

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

Vous n'avez pas besoin/ne pouvez pas utiliser --auth sur la ligne de commande, car le script docker entrypoint.sh l’ajoute lorsque les variables d’environnement existent.

Initialisation de la base de données

L'image fournit également le /docker-entrypoint-initdb.d/ chemin d'accès au déploiement personnalisé .js ou .sh scripts de configuration à exécuter une fois lors de l’initialisation de la base de données. .js Les scripts seront exécutés sur test par défaut ou MONGO_INITDB_DATABASE _ si défini dans l'environnement.

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

ou

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

Un fichier javascript d'initialisation simple qui montre la journalisation et comment sortir avec une erreur (pour la vérification des résultats).

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)
}
59
Matt

Voici une autre solution plus propre en utilisant docker-compose et un script js.

Cet exemple suppose que les deux fichiers (docker-compose.yml et mongo-init.js) se trouvent dans le même dossier.

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

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

Ensuite, démarrez simplement le service en exécutant la commande suivante docker-compose

docker-compose up --build -d mongodb 
25
Paul Wasilewski

Voici une solution de travail qui crée admin-user utilisateur avec mot de passe, base de données supplémentaire (test-db), et test-user dans cette base de données.

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:

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

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

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

La partie délicate était de comprendre que les fichiers * .js étaient exécutés sans authentification. La solution authentifie le script en tant que admin-user dans la base de données admin. MONGO_INITDB_DATABASE admin est essentiel, sinon le script serait exécuté sur la test db. Vérifiez le code source de docker-entrypoint.sh .

16
Mateusz Stefek

Si quelqu'un cherche à savoir comment configurer MongoDB avec authentification à l'aide de docker-compose, voici un exemple de configuration utilisant des variables d’environnement:

version: "3.3"

services:

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

Lorsque vous exécutez docker-compose up _ votre instance Mongo est exécutée automatiquement avec l’autorisation activée. Vous aurez une base de données admin avec le mot de passe donné.

13
user2350644

L'image Mongo peut être affectée par MONGO_INITDB_DATABASEvariable , mais la base de données ne sera pas créée. Cette variable détermine la base de données actuelle lors de l'exécution de /docker-entrypoint-initdb.d/*scripts . Puisque vous ne pouvez pas utiliser les variables d'environnement dans les scripts exécutés par Mongo, je suis allé avec un script Shell:

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:

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

Alternativement, vous pouvez stocker init-mongo.sh dans les configurations (docker config create) et montez-le avec:

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

Et les secrets ne peuvent pas être stockés dans un fichier.

6
x-yuri

Si vous souhaitez supprimer les noms d'utilisateur et les mots de passe de votre fichier docker-compose.yml, vous pouvez utiliser Docker Secrets , voici comment je l'ai abordé.

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

J'ai utilisé le fichier : pour mes secrets, mais vous pouvez aussi utiliser external: et utilise les secrets d'un essaim.

Les secrets sont disponibles pour n’importe quel script du conteneur dans/var/run/secrets

La documentation de Docker a ceci à dire sur le stockage de données sensibles ...

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

Vous pouvez utiliser des secrets pour gérer les données sensibles dont un conteneur a besoin au moment de l'exécution, mais vous ne souhaitez pas stocker dans l'image ou dans le contrôle de source, tels que:

Noms d'utilisateur et mots de passe Certificats et clés TLS Clés SSH Autres données importantes telles que le nom d'une base de données ou d'un serveur interne Chaînes génériques ou contenu binaire (taille maximale de 500 Ko)

3
englishPete