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 \
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.