skip to Main Content

Let’s say I have the following docker compose that consists of 2 services: a nodeJS app and a mongoDB database that is backing it:

version: "3.8"

services:
  mongodb-local:
    image: mongo:latest
    restart: unless-stopped
    env_file: ./.env
    # see: https://stackoverflow.com/questions/52373098/disable-default-authentication-in-mongo-docker
#    environment:
#      - MONGO_INITDB_ROOT_USERNAME=$MONGODB_USER
#      - MONGO_INITDB_ROOT_PASSWORD=$MONGODB_PASSWORD
#      - MONGO_INITDB_DATABASE=$MONGODB_DATABASE
    ports:
      - "27017:27017"
    volumes:
      - db:/data/db
  app:
    depends_on:
      - mongodb-local
    build: .
    restart: unless-stopped
    env_file: ./.env
    ports:
      - 3000:3000
    environment:
      - DB_HOST=mongodb
      - DB_USER=$MONGODB_USER
      - DB_PASSWORD=$MONGODB_PASSWORD
      - DB_NAME=$MONGODB_DATABASE
      - DB_PORT=$MONGODB_DOCKER_PORT
    stdin_open: true
    tty: true

Let’s say that the nodeJS code uses mongoose to kind of bootsrap all the schemas and models, in such a way that once the nodeJS app starts, I can hit specific endpoints to register users, add some data, etc.

What I want to do now is to be able to "seed" the DB in such a way that I create users and/or add data "upon start up" so that when doing: docker-compose up I will get a "seeded" DB with the app ready to use for local develpment.

Now it’s a 2 step process:

  1. run docker-compose up to spin up both services
  2. Run curl commands via postman against the nodeJS app to seed the DB by making mongoose "work".

What I want is a mechanism to "seed" the DB with a few test data upon doing a docker-compose up immediately.

I tried using the curl image like so:

version: "3.8"

services:
  mongodb-local:
    image: mongo:latest
    restart: unless-stopped
    env_file: ./.env
    # see: https://stackoverflow.com/questions/52373098/disable-default-authentication-in-mongo-docker
#    environment:
#      - MONGO_INITDB_ROOT_USERNAME=$MONGODB_USER
#      - MONGO_INITDB_ROOT_PASSWORD=$MONGODB_PASSWORD
#      - MONGO_INITDB_DATABASE=$MONGODB_DATABASE
    ports:
      - "27017:27017"
    volumes:
      - db:/data/db
  app:
    depends_on:
      - mongodb-local
    build: .
    restart: unless-stopped
    env_file: ./.env
    ports:
      - 3000:3000
    environment:
      - DB_HOST=mongodb
      - DB_USER=$MONGODB_USER
      - DB_PASSWORD=$MONGODB_PASSWORD
      - DB_NAME=$MONGODB_DATABASE
      - DB_PORT=$MONGODB_DOCKER_PORT
    stdin_open: true
    tty: true

  curl-run:
    depends_on:
      - mongodb-local
      - app
    image: curlimages/curl
    command: "sleep 20 && curl --location --request POST 'http://localhost:3000/register' 
      --header 'Content-Type: application/json' 
      --data-raw '{
      'username': 'user',
      'password': 'pass',
      'role': 'admin'
    }'"

volumes:
  db:

but, no luck… Any pointers would be greatly appreciated.

I have read about mongodump and restore but didn’t manage to get that working.

Note that if there is an approach to do it directly via a volume or directly against the DB container that would be the best!

Thanks in advance!

2

Answers


  1. Chosen as BEST ANSWER

    I managed to fix this by leveraging a tweak on the mongo image entrypoint: /docker-entrypoint-initdb.d

    Essentially, I copy an init file, in Javascript, that gets copied over into the container entrypoint via the volume configuration and that gets executed on startup, which allows me to achieve what I want: seed the DB with data upon startup!

    Here's my modified docker service for mongoDB:

    services:
      mongodb-local:
        image: mongo:latest
        restart: unless-stopped
        env_file: ./.env
        ports:
          - "27017:27017"
        volumes:
          - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
          - db:/data/db
    

    And, here's my actual "seed" file:

    print('Start #################################################################');
    
    db = db.getSiblingDB('<some db name>');
    
    console.log(db)
    
    db.createCollection('<a collection>');
    
    db.dams.insertMany([ ....]);
    
    ....
    
    print("End #########")
    

  2. Have you tried using /docker-entrypoint-initdb.d?

    From the documentation:

    When a container is started for the
    first time it will execute files with extensions .sh and .js that are
    found in /docker-entrypoint-initdb.d. Files will be executed in
    alphabetical order. .js files will be executed by mongosh (mongo on
    versions below 6) using the database specified by the
    MONGO_INITDB_DATABASE variable, if it is present, or test otherwise.
    You may also switch databases within the .js script.

    The only caveat I see here is that this likely only works on a fresh build (docker-compose up -b) vs. every time it is started. If you don’t care about preserving the data between ups/downs, this should work.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search