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

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


Here another cleaner solution by using docker-compose and a js script.

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

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>"                }            ]        });

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

docker-compose up --build -d mongodb 

Note: The code in the docker-entrypoint-init.d folder is only executed if the database has never been initialized before.


The official mongo image has merged a PR to include the functionality to create databases and admin users at startup.

The database initialisation will run any scripts in /docker-entrypoint-initdb.d/ when there is nothing populated in the /data/db directory.

Database Initialisation

The mongo container image provides the /docker-entrypoint-initdb.d/ path to deploy custom .js or .sh setup scripts that will be run once on database initialisation. .js scripts will be run against test by default or MONGO_INITDB_DATABASE if defined in the environment.

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

or

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

A simple initialisation mongo shell javascript file that demonstrates setting up the container collection with data, logging and how to exit with an error (for result checking).

let error = truelet res = [  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)}

Admin User Setup

The environment variables to control "root" user setup are

  • 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

or Dockerfile

FROM docker.io/mongoENV MONGO_INITDB_ROOT_USERNAME adminENV MONGO_INITDB_ROOT_PASSWORD password

You don't need to use --auth on the command line as the docker entrypoint.sh script adds this in when it detects the environment variables exist.


UPD Today I avoid Docker Swarm, secrets, and configs. I'd run it with docker-compose and the .env file. As long as I don't need autoscaling. If I do, I'd probably choose k8s. And database passwords, root account or not... Do they really matter when you're running a single database in a container not connected to the outside world?.. I'd like to know what you think about it, but Stack Overflow is probably not well suited for this sort of communication.

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

docker-swarm.yml:

version: '3.1'secrets:  mongo-root-passwd:    file: mongo-root-passwd  mongo-user-passwd:    file: mongo-user-passwdservices:  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 = '$MONGO_INITDB_ROOT_PASSWORD';    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.sh in configs (docker config create) and mount it with:

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 couple of gists on the matter.