docker-compose create user in mognodb - mongodb

What is the best solution to create a user and database in MongoDB using docker-compose?
mongo:
restart: always
image: mongo:latest
container_name: "mongodb"
environment:
- MONGODB_USERNAME=test
- MONGODB_PASSWORD=test123
- MONGODB_DATABASE=test1
volumes:
- ./data/db:/var/micro-data/mongodb/data/db
- ./setup:/setup
ports:
- 27017:27017
command: mongod --smallfiles --logpath=/dev/null # --quiet
MONGODB env doesn't work for me.

With https://hub.docker.com/_/mongo/ you need to start the db with auth disabled, wait for mongo to spin up, create a user, restart the container with auth enabled.
https://hub.docker.com/r/bitnami/mongodb/ has a handy script added:
You can create a user with restricted access to a database while starting the container for the first time. To do this, provide the MONGODB_USERNAME, MONGO_PASSWORD and MONGODB_DATABASE environment variables.
$ docker run --name mongodb \
-e MONGODB_USERNAME=my_user -e MONGODB_PASSWORD=password123 \
-e MONGODB_DATABASE=my_database bitnami/mongodb:latest
It seems like you have bitnami environment variables set up, but use the original image image: mongo:latest where they are not being used.
So either use image: bitnami/mongodb:latest, or add the user manually.
Update:
Starting from v3.0 you can benefit from Localhost exception so you don't need to restart the container. Instead you can start it with authentication enabled, wait some time for the server to start listening, create users from within the container, e.g.
docker exec mongo4 mongo test1 \
--eval 'db.createUser({user: "test", pwd: "test123", roles: [ "readWrite", "dbAdmin" ]});'

Related

Unable to name a Mongo database in Docker compose

Can anyone tell me where I am going wrong. All I am trying to do is name a Mongo database using docker compose.
I have a docker compose file that looks like this:
version: "3"
services:
mongo-db:
image: mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
- MONGO_INITDB_DATABASE=mydbname
ports:
- 27017:27017
volumes:
- mongo-db:/data/db
volumes:
mongo-db:
I run docker docker-compose -f docker-compose.yml up -d --build and it runs. I then open Robo 3T and connect to my container but every time I do the database is called test and not mydbname. Any ideas? TIA
The environment variables are only used to create a new database if no database already exists. You map a volume to /data/db and that volume probably contains an existing database named 'test'.
Find the volume using docker volume ls. It's called something like <directory name>_mongo-db. Then delete it using docker volume rm <volume name>.
Now Docker will create a new, empty volume and Mongo will create a new database when you start the container. And it'll use the values from the environment variables.

Can't see my mongo database when using mongo cmd on a Docker container

Similar to Can't connect to MongoDB container from other Docker container - but answers from this post don't work for me.
I am new to Docker. Trying to learn it on a typescript/express/mongo/mongoose api example.
What I am trying to do (and having problems with), is to use mongo cmd line on a running mongo container after it has been spun up using docker compose up. Even though I have my data nicely persisted on a Docker volume, I don't seem to be able to log into the database using cmd line.
This is my docker-compose.yml file:
version: '3.9'
services:
api:
container_name: api_ts
build: .
restart: unless-stopped
environment:
- DB_URL=mongodb://myself:pass123#mongo:27017/
ports:
- '3131:3131'
depends_on:
- mongo
links: # (seems to be needed)
- mongo
mongo:
container_name: mongo_container
image: mongo:latest
restart: always
volumes:
- mongo_dbv:/data/db
environment:
- MONGO_INITDB_ROOT_USERNAME=myself
- MONGO_INITDB_ROOT_PASSWORD=pass123
ports:
- '27017:27017'
volumes:
mongo_dbv: {}
This is my Dockerfile:
FROM node:alpine
WORKDIR /usr/src/app
COPY package*.json .
RUN npm ci
COPY . .
ENV PORT=3131
EXPOSE 3131
COPY .env ./dist
CMD ["npm", "start"]
I am running
docker compose up -d --build
After both services are ready, I do:
docker exec -it mongo_container mongo
show dbs
...and the output of the last cmd is empty
(same occurs when trying to follow the answers in the post mentioned above)
I am sure the database contains data, because I am able to verify it using REST client.
Also, I am a bit puzzled - and maybe this is somehow connected - why there is no indication, either in docker-compose.yml or in Dockerfile, of the database name which I am using. I would expect it to be part of show dbs output. Despite that, my api runs just fine.
Listing databases requires authentication
docker exec -it mongo_container mongo -u myself -p pass123
Now you can list databases
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
Note: mongo should show you warning that "mongo" shell has been superseded by "mongosh". When you use mongosh, a proper authentication error would be shown on the database listing attempt.

Create Mongo docker image and add user to database

I am trying to find a way to create a docker container that when created has the db user profile created automatically. I am using a dockerfile and thought i could add the commands to create the user in it.
Anyone done this before and know what I am doing wrong here. I am no expert at Docker.
FROM mongo:latest
RUN mongo &&\
use tewtdb &&\
db.createUser({user: '<user>', pwd: '<pwrd>', roles[{role: 'dbOwner', db: 'tewtdb'}]})
EXPOSE 27017
CMD ["mongod"]
shell
docker run --name mongodb -d -e MONGO_INITDB_ROOT_USERNAME=user -e MONGO_INITDB_ROOT_PASSWORD=pwd -v D:/mdb:/data/db -p 27117:27017 mongo:5.0
dockerfile-compose
version: '3'
services:
standalone:
image: mongo:5.0
ports:
- 27117:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=user
- MONGO_INITDB_ROOT_PASSWORD=pwd
volumes:
- D:/mdb:/data/db
docker-compose -f docker-compose.yml up -d

how to start postgres prior to run docker

I am super embarrassed to ask this question, because it seems a very basic one, but somehow I can't find the answer in docs.
I have a django app that uses postgres. In docker-compose.yaml there is the following requirement:
version: "2"
services:
database:
image: postgres:9.5
environment:
POSTGRES_DB: ${POSTGRES_DATABASE}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DATA: /var/lib/postgresql/data/pgdata
when I run my docker image:
docker run -it --name myapp myimage
it keeps repeating:
The database is not ready.
wait for postgres to start...
I ran postgres in detached mode: docker run -it -d postgres:9.5
but it does not help
With Docker Compose 2.1 syntax, you can specify healthchecks to control container start-up:
version: '2.1'
services:
application:
depends_on:
database:
condition: service_healthy
Check out https://github.com/docker-library/healthcheck/tree/master/postgres for an example Dockerfile for building Postgres with healthchecks.
Please have a look at this doc.
Second example is exacly what you need:
You create sh script and add it to your app container by using ADD or COPY:
#!/bin/bash
# wait-for-postgres.sh
set -e
host="$1"
shift
cmd="$#"
until psql -h "$host" -U "postgres" -c '\l'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
>&2 echo "Postgres is up - executing command"
exec $cmd
Then you modify your docker-compose.yaml like this:
version: "2"
services:
web:
build: .
ports:
- "80:8000"
depends_on:
- "db"
command: ["./wait-for-postgres.sh", "db", "python", "app.py"]
db:
image: postgres
In command you're orerriding default command of your container.
Of course "python", "app.py" part is depedent on how you start your app.
Fo Java it would be for example "java", "-jar", "my-app.jar" etc.
Everything is OK with the way you start the container, however, the issues you are experiencing it is because the DB and the APP containers are starting one after the other, however, the DB container, needs to prepare the DB, do the migrations and so on, so therefore, by the time your app container tries to reach your DB container it is not ready so that's why you are getting this error.
You have 2 choices, one is to edit your APP Dockerfile and add WAIT for 30 - 60 s or so, or you could just start the DB on its own, wait for it to be ready to go and then start your APP container.

How to create user in mongodb with docker-compose

I'm trying to create some kind of script that will create a docker with mongodb and automatically create a user.
I can usually manage my docker images with docker-compose but this time, I don't know how to do it.
Basically, here is what I have to do:
clean/destroy container (docker-compose down)
create a docker container with mongodb and start it (without --auth parameter)
execute a java script containing db.createUser()
stop the container
restart the same container with --auth parameter to allow login with the user created in the javascript
I can't find how to do that properly with docker-compose because when it starts, I have to give it the command --auth. If I do that, I cannot execute my javascript to add my user. MongoDB allows users creation without being logged in if there is no user and if --auth parameter is not provided.
I want to do that automatically, I do not want to manually do some commands. The goal is to have a script that can be executed before each integration tests to start from a clean database.
Here is my project:
integration-test/src/test/resources/scripts/docker-compose.yml
mongodb:
container_name: mongo
image: mongo
ports:
- "27017:27017"
volumes:
- .:/setup
command: --auth
integration-test/src/test/resources/scripts/docker-init.sh
docker-compose down
docker-compose up -d
sleep 1
docker exec mongo bash -c "mongo myDatabase /setup/mongodb-setup.js"
integration-test/src/test/resources/scripts/mongodb-setup.js
db.createUser(
{
user: "myUser",
pwd: "myPassword",
roles: [
{ role: "readWrite", db: "myDatabase" }
]
})
Finding a way to start again a container with a new parameter (in this case --auth) would help but I can't find how to do that (docker start does not take parameters).
Any idea how I should do what I would like ?
If not, I can still delete everything from my database with some Java code or something else but I would like a complete mongodb docker setup created with a script.
The official mongo image now supports following environment variables that can be used in docker-compose as below:
environment:
- MONGO_INITDB_ROOT_USERNAME=user
- MONGO_INITDB_ROOT_PASSWORD=password
- MONGO_INITDB_DATABASE=test
more explanation at:
https://stackoverflow.com/a/42917632/1069610
This is how I do it, my requirement was to bring up a few containers along with mongodb, the other containers expect a user to be present when they come up, this worked for me. The good part is, the mongoClientTemp exits after the command is executed so the container doesn't stick around.
version: '2'
services:
mongo:
image: mongo:latest
container_name: mongo
ports:
- "27017:27017"
volumes:
- /app/hdp/mongo/data:/data/db
mongoClientTemp:
image: mongo:latest
container_name: mongoClientTemp
links:
- mongo:mongo
command: mongo --host mongo --eval "db.getSiblingDB('dashboard').createUser({user:'db', pwd:'dbpass', roles:[{role:'readWrite',db:'dashboard'}]});"
depends_on:
- mongo
another-container:
image: another-image:v01
container_name: another-container
ports:
- "8080:8080"
volumes:
- ./logs:/app/logs
environment:
- MONGODB_HOST=mongo
- MONGODB_PORT=27017
links:
- mongo:mongo
depends_on:
- mongoClientTemp
EDIT: tutumcloud repository is deprecated and no longer maintained, see other answers
I suggest that you use environment variables to set mongo user, database and password. tutum (owned by Docker) published a very good image
https://github.com/tutumcloud/mongodb
docker run -d -p 27017:27017 -p 28017:28017 -e MONGODB_USER="user" -e MONGODB_DATABASE="mydatabase" -e MONGODB_PASS="mypass" tutum/mongodb
You may convert these variables into docker-compose environments variables. You don't have to hard code it.
environment:
MONGODB_USER: "${db_user_env}"
MONGODB_DATABASE: "${dbname_env}"
MONGODB_PASS: "${db_pass}"
This configuration will read from your session's environment variables.
In your project directory create another directory docker-entrypoint-initdb.d then the
file tree looks like this:
📦Project-directory
┣ 📂docker-entrypoint-initdb.d
┃ ┗ 📜mongo-init.js
┗ 📜docker-compose.yaml
The docker-compose.yml contains:
version: "3.7"
services:
mongo:
container_name: container-mongodb
image: mongo:latest
restart: always
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: root-db
volumes:
- ./docker-entrypoint-initdb.d/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
mongo-init.js contains the javascript code to create user with different roles.
print("Started Adding the Users.");
db = db.getSiblingDB("admin");
db.createUser({
user: "userx",
pwd: "1234",
roles: [{ role: "readWrite", db: "admin" }],
});
print("End Adding the User Roles.");
You can modify the mongo-init.js as you need.
After reading the the official mongo docker page, I've found that you can create an admin user one single time, even if the auth option is being used. This is not well documented, but it simply works (hope it is not a feature).
Therefore, you can keep using the auth option all the time.
I created a github repository with scripts wrapping up the commands to be used. The most important command lines to run are:
docker exec db_mongodb mongo admin /setup/create-admin.js
docker exec db_mongodb mongo admin /setup/create-user.js -u admin -p admin --authenticationDatabase admin
The first line will create the admin user (and mongo will not complain even with auth option). The second line will create your "normal" user, using the admin rights from the first one.
Mongo image provides the /docker-entrypoint-initdb.d/ path to deploy custom .js or .sh setup scripts.
Check this post to get more details :
How to create a DB for MongoDB container on start up?
file: docker-compose.yaml
mongo:
image: mongo:latest
volumes_from:
- data
ports:
- "27017:27017"
command: --auth
container_name: "db_mongodb"
data:
image: mongo:latest
volumes:
- /var/lib/mongo
- ./setup:/setup
command: "true"
container_name: "db_mongodb_data"
file: .buildMongo.sh
#!/bin/sh
docker-compose down
docker-compose up -d
sleep 1
docker exec db_mongodb mongo admin /setup/create-admin.js
docker exec db_mongodb mongo myDb /setup/create-user.js -u admin -p admin --authenticationDatabase admin
The create-admin.js and create-user.js files are commands that you use using the mongo shell. So they must be easy for you to understand. The real direction is like the jzqa answer, "environment variables".
So the question here is how to create a user. I think this answers that point at least, you can check the complete setup here https://github.com/Lus1t4nUm/mongo_docker_bootstrap
For initializing mongo with initial user-password-db triple and initdb scripts with only one docker-compose.yml, without any extra configuration, you can use bitnami/mongo image.
In my case, I didn't run my scripts under /docker-entrypoint-initdb.d directory in the container after setting environment variables; MONGODB_USERNAME and MONGODB_PASSWORD (specific env variables for bitnami image) because mongod runs with --auth option automatically when you set these variables. Consequently, I got authentication errors when the container was in the process of executing the scripts.
Because, it was connecting to: mongodb://192.168.192.2:27017/compressors=disabled&gssapiServiceName=mongodb
TERMINAL LOG OF THE ERROR
FIRST DOCKER-COMPOSE FILE:
version: "3"
services:
mongodb:
container_name: mongodb
image: 'docker.io/bitnami/mongodb:4.2-debian-10'
ports:
- "27017:27017"
volumes:
- "mongodb_data:/bitnami/mongodb"
- "./mongodb/scripts:/docker-entrypoint-initdb.d"
environment:
- MONGODB_INITSCRIPTS_DIR=/docker-entrypoint-initdb.d
- MONGODB_USERNAME=some_username
- MONGODB_PASSWORD=some_password
- MONGODB_DATABASE=some_db_name
networks:
backend:
restart: unless-stopped
volumes:
mongodb_data:
networks:
backend:
driver: bridge
INIT JS FILE UNDER ./mongodb/scripts PATH:
let db = connect("localhost:27017/some_db_name");
db.auth("some_username", "some_password");
let collections = db.getCollectionNames();
let storeFound = false;
let index;
for(index=0; index<collections.length; index++){
if ("store" === collections[index]){
storeFound = true;
}
}
if(!storeFound ){
db.createCollection("store");
db.store.createIndex({"name": 1});
}
So, I decided to add new environment variables to my docker-compose.yml after inspecting https://github.com/bitnami/bitnami-docker-mongodb/blob/master/4.2/debian-10/rootfs/opt/bitnami/scripts/libmongodb.sh file.
In this sh file, there is function like mongodb_custom_init_scripts() for executing the scripts. For executing all script files, it runs mongodb_execute() method. In this method, after mongod instance is up and run, mongo client is connecting to the mongod instance by using some parameters.
########################
# Execute an arbitrary query/queries against the running MongoDB service
# Stdin:
# Query/queries to execute
# Arguments:
# $1 - User to run queries
# $2 - Password
# $3 - Database where to run the queries
# $4 - Host (default to result of get_mongo_hostname function)
# $5 - Port (default $MONGODB_PORT_NUMBER)
# $6 - Extra arguments (default $MONGODB_CLIENT_EXTRA_FLAGS)
# Returns:
# None
########################
mongodb_execute() {
local -r user="${1:-}"
local -r password="${2:-}"
local -r database="${3:-}"
local -r host="${4:-$(get_mongo_hostname)}"
local -r port="${5:-$MONGODB_PORT_NUMBER}"
local -r extra_args="${6:-$MONGODB_CLIENT_EXTRA_FLAGS}"
local result
local final_user="$user"
# If password is empty it means no auth, do not specify user
[[ -z "$password" ]] && final_user=""
local -a args=("--host" "$host" "--port" "$port")
[[ -n "$final_user" ]] && args+=("-u" "$final_user")
[[ -n "$password" ]] && args+=("-p" "$password")
[[ -n "$extra_args" ]] && args+=($extra_args)
[[ -n "$database" ]] && args+=("$database")
"$MONGODB_BIN_DIR/mongo" "${args[#]}"
}
After that I added new environment variables to my docker-compose like MONGODB_ADVERTISED_HOSTNAME, MONGODB_PORT_NUMBER, and, MONGODB_CLIENT_EXTRA_FLAGS
So my final docker-compose.yml looks like:
version: "3"
services:
mongodb:
container_name: mongodb
image: 'docker.io/bitnami/mongodb:4.2-debian-10'
ports:
- "27017:27017"
volumes:
- "mongodb_data:/bitnami/mongodb"
- "./mongodb/scripts:/docker-entrypoint-initdb.d"
environment:
- MONGODB_INITSCRIPTS_DIR=/docker-entrypoint-initdb.d
- MONGODB_USERNAME=some_username
- MONGODB_PASSWORD=some_password
- MONGODB_DATABASE=some_db_name
- MONGODB_ADVERTISED_HOSTNAME=localhost
- MONGODB_PORT_NUMBER=27017
- MONGODB_CLIENT_EXTRA_FLAGS=--authenticationDatabase=some_db_name
networks:
backend:
restart: unless-stopped
volumes:
mongodb_data:
networks:
backend:
driver: bridge
Now, it was connecting by this url:
mongodb://localhost:27017/?authSource=some_db_name&compressors=disabled &gssapiServiceName=mongodb
add --noauth option to the mongo command
extract from my docker-compose.yml file
mongors:
image: mongo:latest
command: mongod --noprealloc --smallfiles --replSet mongors2 --dbpath /data/db --nojournal --oplogSize 16 --noauth
environment:
TERM: xterm
volumes:
- ./data/mongors:/data/db