MongoDB container with Docker Compose

How to run MongoDB container with Docker Compose?

docker-compose.yml

Example container configuration:

services:
    mongodb:
        image: mongo:latest
        container_name: mongodb
        hostname: mongodb
        volumes:
            - ./.docker/mongodb/mongod.conf:/etc/mongod.conf
            - ./.docker/mongodb/initdb.d/:/docker-entrypoint-initdb.d/
            - ./.docker/mongodb/data/db/:/data/db/
            - ./.docker/mongodb/data/log/:/var/log/mongodb/
        env_file:
            - .env
        environment:
            MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
            MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
            MONGO_INITDB_DATABASE: ${MONGO_INITDB_DATABASE}
        ports:
            - "27017:27017"
        command: ["-f", "/etc/mongod.conf"]

What does it all mean?

        image: mongo:latest

Specifies an image to use, in this case the mongo:latest. At the moment of writing this maps to version 4.0.9 based on Ubuntu Xenial.

Optionally, if you want to build your own version of the image, you could replace this line with build: .docker/mongodb and build your own image using the Dockerfile.

        container_name: mongodb

Specifies a custom container name, rather than a generated default name.

        hostname: mongodb

Analogous to its docker run counterpart, it sets the container hostname modifying its /etc/hosts file. Needed for example by Mongo Express container to be able to connect and reconnect to the database without issues.

        volumes:

Mounts host paths or named volumes, specified as sub-options to a service.

In case of the above configuration:

            - ./.docker/mongodb/mongod.conf:/etc/mongod.conf

will mount local .docker/mongodb/mongod.conf file as /etc/mongod.conf in the container, allowing easy modifications to MongoDB configuration.

            - ./.docker/mongodb/initdb.d/:/docker-entrypoint-initdb.d/

will mount local .docker/mongodb/initdb.d/ directory as /docker-entrypoint-initdb.d/ in the container, allowing easy modifications to .sh and .js container initialization files.

            - ./.docker/mongodb/data/db/:/data/db/

will mount local .docker/mongodb/data/db/ directory as /data/db/ in the container, storing MongoDB database files locally.

            - ./.docker/mongodb/data/log/:/var/log/mongodb/

will mount local .docker/mongodb/data/log/ directory as /var/log/mongodb/ in the container, storing MongoDB log files locally.

        env_file:
            - .env

Add environment variables from a file. Can be a single value or a list.

        environment:
            MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
            MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
            MONGO_INITDB_DATABASE: ${MONGO_INITDB_DATABASE}

Add environment variables, either as an array or a dictionary.

        ports:
            - "27017:27017"

Port mapping defined in short syntax: HOST:CONTAINER.

27017:27017 means that port 27017 on host will forward all its traffic to port 27017 in the container, served by mongod service (see .docker/mongodb/mongod.conf).

        command: ["-f", "/etc/mongod.conf"]

Override the default command to start the service in the container.

The default mongo image command to start mongod service is just mongod, which does not use the /etc/mongod.conf configuration file. I fwe want to use it, we need to start mongod with the -f parameter.

.docker/mongodb/mongod.conf

# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# Where and how to store data.
storage:
  dbPath: /data/db
  journal:
    enabled: true
#  engine:
#  mmapv1:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1


# how the process runs
processManagement:
  timeZoneInfo: /usr/share/zoneinfo

security:
  authorization: enabled

#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:

.docker/mongodb/initdb.d/create-app-user.sh

#!/bin/bash
# https://www.stuartellis.name/articles/shell-scripting/#enabling-better-error-handling-with-set
set -Eeuo pipefail

# Based on mongo/docker-entrypoint.sh
# https://github.com/docker-library/mongo/blob/master/docker-entrypoint.sh#L303
if [ "$MONGO_INITDB_USERNAME" ] && [ "$MONGO_INITDB_PASSWORD" ]; then
    "${mongo[@]}" -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" --authenticationDatabase "$rootAuthDatabase" "$MONGO_INITDB_DATABASE" <<-EOJS
        db.createUser({
            user: $(_js_escape "$MONGO_INITDB_USERNAME"),
            pwd: $(_js_escape "$MONGO_INITDB_PASSWORD"),
            roles: [ { role: 'readWrite', db: $(_js_escape "$MONGO_INITDB_DATABASE") } ]
        })
    EOJS
fi

.env.dist

# MongoDB
MONGO_URL=mongodb://mongodb:27017
MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=root
MONGO_INITDB_DATABASE=symfony
MONGO_INITDB_USERNAME=symfony
MONGO_INITDB_PASSWORD=symfony
MONGO_REPLICA_SET_NAME=rs0

.docker/mongodb/Dockerfile

Optionally, if you want to build your own version of the image, and for example additionally install mongo-hacker shell enhancement, in your docker-compose.yml file you can replace image: mongo:latest with build: .docker/mongodb and build your own image using the appropriate Dockerfile, for example:

FROM mongo:latest

RUN apt-get update \
    && apt-get install -y git build-essential \
    && git clone --depth=1 https://github.com/TylerBrock/mongo-hacker.git \
    && rm -rf ~/.mongorc.js \
    && cd mongo-hacker \
    && make install

CMD ["mongod", "-f", "/etc/mongod.conf"]