Seed Your MongoDB Container with JSON data using Docker and Docker-Compose


A couple of years ago I made a frontend app which rendered JSON data stored in-memory. The App provided a check-list for Quality Management called QualiExplore (under Apache 2.0 License).

Nothing too fancy, but we needed to make the app a bit more flexible and decided to use MongoDB to render the information as well as make it easy to introduce new information to the JSON data that previously persisted in the App.

Fundamentally, the app should be out-of-the-box usable for someone who wants to use it (with other additions currently on-going e.g., GraphQL backend + User authentication / authorization)


The JSON data, that previously persisted in the app needs to be seeded into the MongoDB instance once the complete stack is brought up.

Doesn’t sound like a bit deal, should be possible to use volume mounts with docker, right? Yup, you guessed it but MongoDB doesn’t just ingest data because one mounted a volume to a specific directory. To the rescue comes mongoimport tool where one can load data via CLI. Seems like our problem is solved!

We it turns out I wanted to seed data into the MongoDB in a litte more secure manner aka. maybe use a username and password and a dedicated initialized database where this imported data should persist under specific collections.

Turns out, once you figure out the mongoimport tool’s Syntax, the next big headache was to figure out how to securely pass this information to a docker image which will insert this information into Mongo.

I generally have a stack design pattern where I try to keep changes into YAML files for an end-user minimum and let the changes reflect through the environment variables passed to the stack. So passing the environment variables to the respective docker containers shouldn’t be a big hassle, right? Oh! how wrong I was!


I decided to following the following sequential steps:

  1. Bring the MongoDB container up
  2. Create a docker container that is connected to the same network as MongoDB container as above that has mongoimport on it
  3. Mount the JSON data into the container in step 2 and insert the data
  4. In order to make the ingestion of data bit more secure pass the information like the database’s URI, credentials via environment variables

So the initial project setup is as follows:

├── docker-compose.yml
├── mongo_seed
│   ├── Dockerfile
│   ├── factors.json
│   └── filters.json
└── .env

Here, the mongo_seed is the directory with the data to be ingested as well as the Dockerfile that will perform the necessary ingestion.

The root of the directory contains the docker-compose.yml for the stack and its respective .env file for environment variables

Problems Faced

This requires a quick primer of Docker’s ARG and ENV in context of docker. A decent read-through I used can be found here

In a nutshell

ARG is used during build-time i.e., when building a docker container. It’s lifetime is short till the build is complete. Once the container is built, they are not available for further usage. ENV, on the other hand, is available for the run-time of the container too.

A common practice that a lot of container developers use is to declare an ARG and then use the value of the incoming build-argument as an ENV for further usage.

so something like

ARG database-uri

ENV DATABASE_URI=$(database-uri)

# Use `$DATABASE_URI` to insert database

This wasn’t the case since I ended facing problem which I documented on StackExchange

The problem concisely, is the environment variables from .env fille passed into the mongo-seed container doesn’t get set during run-time


After going through some StackExchange Queries, an answer from Zincfan on a Query regarding getting Env Variable in Dockerfile turned out to be the solution


  • Declare Same ARG and ENV of the same name as that of the environment variables
  • Get the information from the build-argument and store the information into the env. variable using the syntax: ARG DATABASE_URI ENV DATABASE_URI ${DATABASE_URI}
  • use ${DATABASE_URI} in the run-time of the container
  • to pass the information from the .env passed to the compose file should be in the following way:
                  - DATABASE_URI=$DATABASE_URI


So finally my Dockerfile looks like the following:

FROM mongo:5.0
 # Will be set through Environment Files


 COPY factors.json /factors.json

 COPY filters.json /filters.json

 CMD mongoimport --username ${USERNAME} --password ${PASSWORD} --uri ${DATABASE_URI} --collection factors --drop --file /factors.json && \
     mongoimport --username ${USERNAME} --password ${PASSWORD} --uri ${DATABASE_URI} --collection filters --drop --file /filters.json

Good to Note: Never split into two CMD in the file, rather merge multiple commands into one CMD.

my docker-compose.yml file looks like the following:

    # MongoDB
        container_name: mongodb
        image: mongo:latest
            - .env
            - "27017:27017"
            - "qualiexplore_net"

    # Initial Seed to QualiExplore Database
            - .env
            context: ./mongo_seed
            dockerfile: Dockerfile
                - DATABASE_URI=$DATABASE_URI
            - mongo
            - "qualiexplore_net"

My .env file is as follows:


Comments, Suggestions

If you would like to suggest me some changes in my design or a better way to tackle this situation, I am all ears and would love to improve and discuss aspects. You can contact me on LinkedIn or via E-Mail.