Docker + Mongo: a guide

Load data with js or sh

Docker + Mongo: a guide

posted in docker on  •   •  • last updated on

How to load some initial data after spinning up a mongo with Docker.

If you want to follow the examples:

git clone https://github.com/itenium-be/Docker-Mongo
cd Docker-Mongo
docker compose up -d --build

# After fiddling, force re-creating the mongos:
docker compose down -v
docker compose up -d --build

Simple Run

docker run --name some-mongo \
  -e MONGO_INITDB_ROOT_USERNAME=mongoadmin \
  -e MONGO_INITDB_ROOT_PASSWORD=pwd \
  -p 27017:27017
  -d mongo

Initial Load

Scripts are executed in alphabetical order, executed on MONGO_INITDB_DATABASE.

For Mongo <6 by mongo and by mongosh for mongo >=6.

See the Github Docker-Mongo Repository for these examples.

With JavaScript

Example compose.yaml file:

services:
  mongo-js:
    container_name: mongo-js-load
    image: mongo
    volumes:
      - db-js:/data/db
      - ./load-js:/docker-entrypoint-initdb.d
    ports:
      - "27009:27017"
    environment:
      MONGO_INITDB_DATABASE: jsapp
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PWD}

volumes:
  db-js: {}

The .env file:

MONGO_USER=mongoadmin
MONGO_PWD=pwd

The load-js directory contains a load.js file:

db.celebrities.insertMany([
  { name: "Jon Skeet" },
  { name: "Martin Fowler" },
  { name: "Erich Gamma" }
]);

With Shell

services:
  mongo-sh:
    container_name: mongo-sh-load
    image: mongo
    volumes:
      - db-sh:/data/db
      - ./load-sh/scripts:/docker-entrypoint-initdb.d
      - ./load-sh/data:/mongo-seed-jsons
    ports:
      - "27008:27017"
    environment:
      MONGO_INITDB_DATABASE: shapp
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PWD}

volumes:
  db-sh: {}

In load-sh/data put your json files to be imported.

You can either already provide the ids in the json with "_id": { "$oid": "5bb0b3050581bf10c4bb89c3" } or omit the _id to have mongo create one for you.

In load-sh/scripts you can import the jsons with a .sh file:

# A json with an []
mongoimport --db $MONGO_INITDB_DATABASE \
  --collection celebrities \
  --jsonArray \
  --file /mongo-seed-jsons/celebrities.json \
  --authenticationDatabase admin \
  --username $MONGO_INITDB_ROOT_USERNAME \
  --password $MONGO_INITDB_ROOT_PASSWORD

# A json with a single {}
mongoimport --db $MONGO_INITDB_DATABASE \
  --collection socials \
  --file /mongo-seed-jsons/socials.json \
  --authenticationDatabase admin \
  --username $MONGO_INITDB_ROOT_USERNAME \
  --password $MONGO_INITDB_ROOT_PASSWORD

Mongo Shell

# With mongo-js-load the name of the container
# And jsapp the database name
docker exec -it mongo-js-load mongosh \
  --username mongoadmin \
  --password pwd \
  --authenticationDatabase admin \
  jsapp

In the shell:

db.celebrities.find()

use admin
show collections
exit

If you just want to bash into it:

docker exec -it mongo-js-load sh

mongod.conf

By default mongo will not load any conf file. If you want to work with a custom mongod.conf:

services:
  mongo-conf:
    container_name: mongo-conf
    image: mongo
    command:
      - '-f'
      - '/etc/mongod.conf'
    volumes:
      - db-conf:/data/db
      - ./mongod.conf:/etc/mongod.conf
    ports:
      - "27007:27007"
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PWD}

volumes:
  db-conf: {}

The container port is 27007 because of this mongod.conf:

net:
  port: 27007
  bindIp: 127.0.0.1

Inside the container check /etc/mongod.conf.orig for a basic one. Or if you have installed it locally:

Platform Install Method Configuration File
Linux apt, yum or zypper /etc/mongod.conf
macOS brew /usr/local/etc/mongod.conf (Intel processor)
    /opt/homebrew/etc/mongod.conf (Apple M1 processors)
Windows MSI <install directory>\bin\mongod.cfg

Security

Get into the mongosh without credentials and then do everything in the shell itself.

See User Management Methods in the mongo docs for more!

docker exec -it mongo-secure mongosh

use admin
db.auth("mongoadmin", "pwd")

use otherDb
db.createUser({
  user: 'otherDbReader',
  pwd: 'pwd',
  roles: [{
    role: 'read',
    db: 'otherDb'
  }]
})

With Initial Load

In a js file. Mongo 6 supports process.env:

db.createUser({
  user: 'user2',
  pwd: process.env.USER2_PWD,
  roles: [{
    role: 'read',
    db: 'someDb'
  }]
})

Before mongo 6, use a sh file instead:

mongosh <<EOF
use $MONGO_INITDB_DATABASE
db.createUser({
  user: '$OTHER_USER',
  pwd: '$OTHER_PWD',
  roles: [{
    role: 'read',
    db: '$MONGO_INITDB_DATABASE'
  }]
})
EOF

Roles

The official docs for Built-In Roles.

Role Description
  Database User Roles
read Read data on all non-system collections (+ system.js)
readWrite Can modify all collections from the read role
  Database Administration Roles
dbAdmin Schema-related tasks, indexing and gathering statistics
userAdmin Create and modify roles and users on the current db. Can grant any privilege to any user, including themselves (indirectly provides superuser to the db/cluster)
dbOwner Combines readWrite, dbAdmin and userAdmin
backup Minimal privileges for backing up data
restore Minimal privileges for restoring backups

Other roles:

  • readAnyDatabase: the same as the roles above, but for all databases (also exists for readWrite, dbAdmin and userAdmin)
  • clusterAdmin: clusterManager + clusterMonitor + hostManager (+ dropDatabase action)
  • enableSharding: Enable sharding for a collection nad modify existing shard keys
  • root: global superuser access: xxxAnyDatabase + clusterAdmin + backup/restore

Synology

If you run these examples on Synology, chances are they won’t work! You may see the following error:

WARNING: MongoDB 5.0+ requires a CPU with AVX (Advanced Vector Extensions) support, and your current system does not appear to have that!

Check here to see if yours has AVX. Basically all models from the 21+, 22+, 23+ 24+ series.

You’ll also run against a permissions issue when executing the js or sh files, which we’ll fix with a custom Dockerfile:

services:
  mongo-synology:
    container_name: mongo-syno-load
    build:
      context: ./load-syno
      dockerfile: Dockerfile
    volumes:
      - db-syno:/data/db
    ports:
      - "27006:27017"
    environment:
      MONGO_INITDB_DATABASE: synoapp
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PWD}

volumes:
  db-syno: {}

The load-syno/Dockerfile file:

# Last version without AVX:
FROM mongo:4.4.29

# Copy your sh file and adjust permissions:
COPY import.sh /docker-entrypoint-initdb.d
RUN chmod +x /docker-entrypoint-initdb.d/import.sh

CMD ["mongod"]

Stuff that came into being during the making of this post
Other interesting reads
Updates
  • 14 September 2024 : Added mongo-secure
Tags: synology mongo