Jakub Bláha
Jakub Bláha

Reputation: 1619

Creating a mongodb user from env variables

Let's say we are using docker and docker-compose for our flask + MongoDB application and we need to interact with the database from within the flask application. The username and password of the DB user, which is used to interact with the database, should be defined inside environent variables as that is the most secure way of storing this sort of data. We can use three different environment variables as shown in the mongo docker image docs, from which two of these variables are interesting to us, MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD. We could define the root user in this way and use it in our flask application, however this is not the best security practice. Now, as stated in the docs, we can define another user using the docker-entrypoint-initdb.d/somefile.js, but the problem is, I didn't find a way to use environment variables inside the js file, which means if I defined variables, let's say, MONGO_USER and MONGO_PASS inside the docker-compose.yml environemnt section, I wouldn't be able to use them to create the database non-root user.

If I could use the environment variables inside the js file, the file would look similar to the one below.

db.createUser(
    {
        user: $MONGO_USER,
        pwd: $MONGO_PASS,
        roles: [
            {
                role: "readWrite",
                db: "my_database"
            }
        ]
    }
);

Obviously and unfortunately, I cannot use environemnt variables inside js files like this.

My question is.. How can I create non-root user using environment variables when using docker-compse and the docker mongo image? Are there any better practices accessing a MongoDB database? Should I perhaps not create the database user programatically at all when the container is being started? Sould I create the users manually using the root account after the container is started?

Upvotes: 0

Views: 2664

Answers (2)

Robin-Manuel Thiel
Robin-Manuel Thiel

Reputation: 2256

You can access the environment variables of the Docker container in your init-mongo.js like this:

db.createUser({
    user: process.env.MONGO_USER,
    pwd: process.env.MONGO_PASSWORD,
    roles: ["readWrite"],
});

Your Docker Compose file would then be:

version: '3'
services
  mongodb:
    image: "mongo:6.0.12"
    ports:
      - "27017:27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password123
      - MONGO_INITDB_DATABASE=eve
      - MONGO_USER=eve
      - MONGO_PASSWORD=password456
    volumes:
      - mongodb:/data/db
      - ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js

volumes:
  mongodb:

Upvotes: 0

pintxo
pintxo

Reputation: 2155

We tried the same route, and ended up with a custom docker image setting up the db accounts.

For our development environment, we created a custom docker image. With a custom entrypoint script creating the desired users.

This will however store passwords in the image and should NEVER be done for any publicly accessible database. It's acceptable at our place only becaus this image is only used on developer machines. And we do not use docker as deployment mechanism for mongodb outside of development, so there is no risk for this image to being used in production.

Dockerfile

FROM mongo:3.6

RUN mkdir -p /var/lib/mongodb && chmod ugo+rwx /var/lib/mongodb

COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

CMD ["mongod", "--auth", "--smallfiles", "--bind_ip_all", "--dbpath", "/var/lib/mongodb"]

entrypoint.sh

#!/bin/bash
# MongoDB Entrypoint

echo "MongoDB Entrypoint called"

# run mongod WITHOUT auth
mongod --smallfiles --dbpath /var/lib/mongodb &
sleep 10

# setup
echo "db.system.version.remove({});" | mongo admin
echo "db.system.version.insert({ '_id' : 'authSchema', 'currentVersion' : 3 });" | mongo admin

# add users
echo "db.createUser({user: 'admin',             pwd: '***', roles: ['root']});"      | mongo admin
echo "db.createUser({user: 'service',           pwd: '***', roles: ['readWrite']});" | mongo service
# echo "db.dropUser('test2');"                                                       | mongo test2

# shutdown server WITHOUT auth
mongod --dbpath /var/lib/mongodb --shutdown

# execute any further commands
exec "$@"

Upvotes: 1

Related Questions