Reputation: 1619
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
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
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.
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"]
#!/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