Setting up a MongoDB instance quickly with docker

With docker there is much less reason to install and use major utilities on your local system unless it is not practical to containerize them. Anytime I want to set up a new MongoDB instance I use a docker image.

This setup will use docker-compose

I use docker compose in order to set up the volume, authentication for new databases. Then the compose file can serve as a template for setting up other databases.

The database volume

The database volume should be a named volume in compose if you want the db to be persistent, or external if it already exists. If you don’t need either of those things, then an unnamed volume will work fine, but remember that it will be deleted when the container exits.

The official mongodb images allow setting up auth

You can configure the user/pass for access to the db such that when the container is brought up the image entrypoint script pulls them in and sets those values so the new database immediately has authentication. Then if you push the container into a production environment later it will already have authentication setup.

How to determine args used by an image container

The official images are pretty easy to peruse and indicate what variables they use to set things up. Look at the Dockerfile and the docker-entrypoint.sh, which for mongodb:4.2 are here: Mongo 4.2 repo. The entrypoint script is called by ENTRYPOINT toward the end of the dockerfile. This should show the configuration options/variables if the documentation does not.

I usually set up the db user/pass in secrets

They can also be passed as ENV variables, but I prefer not having them available much of anywhere, if possible. I set the user and password values in separate text files, make them into secrets, and pull them into the container, specifying the location of those files in env variables so that the container scripts can find them.

A mongodb container, with auth, from scratch

services:

  mongodb:
    container_name: mongoFresh
    image: mongo:4.2-bionic
    restart: always
    environment:
      MONGO_DATA_DIR: /data/db
      MONGO_LOG_DIR: /data/logs
      MONGO_INITDB_ROOT_USERNAME_FILE: /run/secrets/db_user
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/db_pass
    secrets:
      - db_user
      - db_pass
    volumes:
      - type: volume
        source: mongo_data
        target: /data/db
    command: mongod --auth --port 27017
    ports:
      - '27017:27017'

volumes:
  mongo_data:

secrets:
  db_user:
    file: mongo_user.txt
  db_pass:
    file: mongo_pass.txt

details; the secrets

The secrets are derived from files so that the user/pass are not exposed inside the docker config or in environment variables on the container. Those secrets are mounted to the container, and environment variables are set to let the container setup to know where to look for root user/pass files.

Secrets only apply to intial db creation

Once the db has been created, the secrets are ignored. It will not change or update the user/pass once the db has been created the first time this container is brought up.

The volume

This is a new database I am populating, so I created a named volume. If I were to then want to use this database elsewhere I would use this volume as an external one, and the secrets would not be needed.

Using —auth vs not; should only not for resetting auth

mongod —auth forces use of authentication and enforces user roles. It is best to always use this once a user/pass is set up. If you initialize the contianer with a user and pass like I show above then you should be able do this right from the start.

Leave it off if you need to fix/change user/auth

In my long password exuberance I have set passwords that were either invalid or had a character error in my records. Restarting without —auth allowed me to change the password because authentication for the db is disabled entirely. I think I had too large a set of special characters in that case.

starting up the container

I usually use the -p flag (project name) and -f flag (compose file) so that I am explicit about what is being run, and because I sometimes keep a bunch of similar projects in one directory and giving them specific, different project names avoids any collisions.

cd ~/path/to/
docker-compose -f mongo-compose.yml -p newmongo up -d  

And stopping it

Also need to specify the project if one was set when starting the container up.

docker-compose -f mongo-compose.yml -p newmongo down  

Connecting to the the docker container

Use the docker exec command and get a shell in the container. If using the ubuntu xenial version, bash is available.

docker exec -ti mongoFresh /bin/bash

Choosing passwords

I like to generate a random, long password in the shell. You could do it any way you like though, with the main point being to not expose a mongdb instance without authentication at all to the web at some point, which seems to be a somewhat common thing to do because mongodb has no authentication by default.

< /dev/urandom tr -dc 'A-Za-z0-9' | head -c${1:-80};echo;

Logging in

These will be the credentials you put in the username and pass text files, so don’t be surprised when this stock version does not work.

mongo admin -u username -p 'password_of_some_sort'   

B. Alternate setup; using an existing db in a volume -

In this case there is no point passing any configs because mongodb will see the database and load it without attempting any modifications to it, so user/pass would be ignored if they were provided.

Compose file for this arrangement

This pulls in an external volume, does not bother with the user/pass since that will all be according to the existing db, even if it has no authentication.

  secrets:  
services:  
  mongodb:  
    container_name: mongozilla  
    image: mongo:4.0-xenial  
    restart: always  
    environment:  
      MONGO_DATA_DIR: /data/db  
      MONGO_LOG_DIR: /data/logs  
    volumes:  
      - type: volume  
        source: datatodb_mongodata  
        target: /data/db  
    command: mongod --auth --port 27018  

volumes:  
  datatodb_mongodata:  
    external: true  

This can be useful when the db came from elsewhere

This setup makes it easy to start using a database that came from somewhere else, anywhere really, as long as you can get its files onto a docker container. If that db is not compatible with mongo v4, use one of the older 3.x images.