MongoDB single instance replicaset with Docker

Setting up a MongoDB Docker instance that supports oplog tailing and change streams for development


MongoDB single instance replicaset with Docker

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.