MongoDB single instance replicaset with Docker

MongoDB replicasets are required for oplog tailing and subscribing to change stream events. When running a single instance with these features on Docker, finding the correct configuration can be challenging. After working through this setup, I’m sharing a working solution that enables both features in a development environment.

FROM mongo:latest

ARG MONGO_INITDB_ROOT_USERNAME
ENV MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
ARG MONGO_INITDB_ROOT_PASSWORD
ENV MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}

ARG MONGO_KEYFILE_KEY
ARG CONTAINER_HOSTNAME
ENV CONTAINER_HOSTNAME=${CONTAINER_HOSTNAME}
ARG PORT
ENV PORT=${PORT}
ENV HOST_PORT="${CONTAINER_HOSTNAME}:${PORT}"

USER root

RUN echo ${MONGO_KEYFILE_KEY} > "/tmp/replica.key"
RUN chmod 400 /tmp/replica.key
RUN chown 999:999 /tmp/replica.key

EXPOSE ${PORT}

HEALTHCHECK --interval=5s --timeout=30s --start-period=5s --retries=30 \
  CMD echo "rs.initiate({_id: 'rs0', members: [{_id: 1, host: \"${HOST_PORT}\"}]})  || rs.status().ok" | \
    mongosh -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --port ${PORT} --quiet

CMD ["--replSet", "rs0", "--bind_ip_all", "--keyFile", "/tmp/replica.key", "--port=$PORT"]

The Dockerfile uses build arguments and environment variables to configure the root username and password, custom keyfile key, hostname, and port.

Environment Configuration

For local testing, create a .env file with the following values:

MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=your-own-very-secret-password
MONGO_KEYFILE_KEY='*********'
CONTAINER_HOSTNAME=mongodb
PORT=27017

Generating the Keyfile

Generate the required authentication key using OpenSSL:

openssl rand -base64 756

Building the Docker Image

Build the image using the environment variables:

docker build -t mongo_rs0 \
  --build-arg MONGO_INITDB_ROOT_USERNAME="$MONGO_INITDB_ROOT_USERNAME" \
  --build-arg MONGO_INITDB_ROOT_PASSWORD="$MONGO_INITDB_ROOT_PASSWORD" \
  --build-arg MONGO_KEYFILE_KEY="$MONGO_KEYFILE_KEY" \
  --build-arg CONTAINER_HOSTNAME="$CONTAINER_HOSTNAME" \
  --build-arg PORT="$PORT" .

Alternatively, generate the build command automatically from the .env file:

while IFS= read -r line; do
  arg=$(echo $line | cut -d '=' -f 1)
  val=$(echo $line | cut -d '=' -f 2)
  build_args+=" --build-arg $arg=$val"
done < .env
docker build $build_args .

Running the Container

Start the container using the environment file:

docker run --name mongodb --env-file .env mongo_rs0

Integration with CapRover

This configuration works seamlessly with CapRover, which automatically uses environment variables as both build arguments and container environment variables.