Javier Guzmán
Javier Guzmán

Reputation: 1183

How can I pass environment variables to mongo docker-entrypoint-initdb.d?

I am trying to do the following tutorial: https://itnext.io/docker-mongodb-authentication-kubernetes-node-js-75ff995151b6

However, in there, they use raw values for the mongo init.js file that is placed within docker-entrypoint-initdb.d folder.

I would like to use environment variables that come from my CI/CD system (Gitlab). Does anyone know how to pass environment variables to the init.js file? I have tried several things like for example use init.sh instead for the shell but without any success.

If I run manually the init shell version, I can have it working because I call mongo with --eval and pass the values, however, the docker-entrypoint-blabla is called automatically, so I do not have control of how this is called and I do not know what I could do for achieving what I want.

Thank you in advance and regards.

Upvotes: 12

Views: 20603

Answers (7)

dikey9109
dikey9109

Reputation: 1

I dont't know, is it needs yet, but I find the solution for docker-compose with mongo-init.js.

My docker-compose.yml:

services:
  mongo-0:
    image: mongo:7.0.16
    ...
    environment:
      ...
      - CUSTOM_USER_DB_USERNAME=local_user
      - CUSTOM_USER_DB_PASSWORD=local_password
    volumes:
      ...
      - E://GIT/Mongo/scripts/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

And my mongo-init.js:

let dbName = 'aaa';
db = db.getSiblingDB(dbName);

const userCreationResult = db.createUser({
    user: process.env.CUSTOM_USER_DB_USERNAME,
    pwd: process.env.CUSTOM_USER_DB_PASSWORD,
    roles: [
        { role: 'readWrite', db: dbName }
    ]
});

Upvotes: 0

Edan Kriss
Edan Kriss

Reputation: 111

Until recently, I simply used a .sh shell script in the docker-entrypoint-initdb.d directory to access ENV variables, much like @Lazaro answer.

It is now possible to access environment variables from javascript files using process.env, provided the file is run with the newer mongosh instead of mongo, which is now deprecated.

However, according to the Docs (see 'Initializing a fresh instance'), mongosh is only used for .js files in docker-entrypoint-initdb.d if using version 6 or greater. I can confirm this is working using the mongo:6 image tag.

Upvotes: 2

jacob
jacob

Reputation: 518

I prefer this method because it allows you to keep a normal .js file which you lint instead of embedding the .js file into a string.

Create a dockerfile like so:

FROM mongo:5.0.9

USER mongodb
WORKDIR /docker-entrypoint-initdb.d
COPY env_init_mongo.sh env_init_mongo.sh

WORKDIR /writing
COPY mongo_init.js mongo_init.js

WORKDIR /db/data

At the top of your mongo_init.js file, you can just define variables you need

db_name = DB_NAME
schema_version = SCHEMA_VERSION

and then in your env_init_mongo.sh file, you can just replace the strings you need with environment variables or add lines to the top of the file:

mongo_init="/writing/mongo_init.js"
sed "s/SCHEMA_VERSION/$SCHEMA_VERSION/g" -i $mongo_init
sed "s/DB_NAME/${MONGO_INITDB_DATABASE}/g" -i $mongo_init
sed "1s/^/use ${MONGO_INITDB_DATABASE}\n/" -i $mongo_init # add to top of file
mongo < $mongo_init

Upvotes: 0

you can make use of a shell script to retrieve env variables and create the user.

initdb.d/init-mongo.sh

set -e

mongo <<EOF
use $MONGO_INITDB_DATABASE

db.createUser({
  user: '$MONGO_INITDB_USER',
  pwd: '$MONGO_INITDB_PWD',
  roles: [{
    role: 'readWrite',
    db: '$MONGO_INITDB_DATABASE'
  }]
})
EOF

docker-compose.yml

version: "3.7"

services:
  mongodb:
    container_name: "mongodb"
    image: mongo:4.4
    hostname: mongodb
    restart: always
    volumes:
      - ./data/mongodb/mongod.conf:/etc/mongod.conf
      - ./data/mongodb/initdb.d/:/docker-entrypoint-initdb.d/
      - ./data/mongodb/data/db/:/data/db/
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=root
      - MONGO_INITDB_DATABASE=development
      - MONGO_INITDB_USER=mongodb
      - MONGO_INITDB_PWD=mongodb
    ports:
      - 27017:27017
    command: [ "-f", "/etc/mongod.conf" ]

Now you can connect to development database using mongodb as user and password credentials.

Upvotes: 20

senyor
senyor

Reputation: 352

Use shell script (e.g mongo-init.sh) to access variables. Can still run JavaScript code inside as below.

set -e

mongo <<EOF
use admin

db.createUser({
  user: '$MONGO_ADMIN_USER',
  pwd:  '$MONGO_ADMIN_PASSWORD',
  roles: [{
    role: 'readWrite',
    db: 'dummydb'
  }]
})
EOF

Shebang line is not necessary at the beginning as this file will be sourced.

Upvotes: 1

Javier Guzm&#225;n
Javier Guzm&#225;n

Reputation: 1183

At the end the answer is that you can use a .sh file instead of a .js file within the docker-entrypoint-initdb.d folder. Within the sh script, you can use directly environment variables. However, I could not do that at the beginning because I had a typo and environment variables were not created properly.

Upvotes: 0

Andy
Andy

Reputation: 429

You can use envsubs. If command not found : here. Install it on your runners host if you use shell runners, else, within the docker image used by the runner, or directly in your script.

(NB: Your link isn't free, so I can't adapt to your situation :p )

Example:

init.js.template:

console.log('$GREET $PEOPLE $PUNCTUATION')
console.log('Pipeline from $CI_COMMIT_BRANCH')

gitlab_ci.yml:

variables:
  GREET: "hello"
  PEOPLE: "world"
  PUNCTUATION: "!"
# ...
script:
  - (envsubst < path/to/init.js.template) > path/to/init.js
  - cat path/to/init.js

Output:

$ (envsubst < init.js.template) > init.js
$ cat init.js
console.log('hello world !')
console.log('Pipeline from master')

Upvotes: 0

Related Questions