I've been working on a project for a little while now using SpringBoot (Java) for the backend REST API and an Angular (12) application on the frontend. Using MongoDB in a Docker container with SpringBoot was working well until a recent upgrade to my libraries, here's how I fixed it.

Gradle config

For future reference, upgrading to these dependencies seemed to have caused the original issue:
This is not a complete gradle config, just included bits I think are relevant.

plugins {
    id 'org.springframework.boot' version '2.6.5'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}
repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
    maven { url 'https://repo.spring.io/snapshot' }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-tomcat'

    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.security:spring-security-test'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
}

annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"

Why run MongoDB in Docker rather than natively

My home system runs Fedora Linux. Unfortunately the MongoDB licence is incompatible with the Fedora project, so it no longer exists in the project repositories to install with the usual package manager (dnf).

I had decided to use MongoDB when they made a version freely available. Until then I was using ArrangoDB, but I've been meaning to play with MongoDB for a while.

Step up Docker containers.

By deploying MongoDB in Docker I avoid the need to install on my system, so I sidestep the need to install (and manage upgrades for) software independently to the system package manager. I avoid the need to add additional repositories.

Docker container setup

I use docker-compose to launch my container with 'docker-compose up'.

My MongoDB docker-compose.yml :

version: "3.8"
services:
  mongodb:
    container_name: mongodb
    image: mongo:latest
    hostname: mongodb
    environment:
      - MONGO_INITDB_ROOT_USERNAME=mongoroot
      - MONGO_INITDB_ROOT_PASSWORD=pass12345
      - MONGO_INITDB_DATABASE=datastore
      - DB_NAME=datastore
      - APP_USER=app_user
      - APP_PWD=appuserpwd
    ports:
      - 27017:27017
    expose:
      - 27017
    restart: unless-stopped

This seemed to bring up my MongoDB container ok, but for some reason my SpringBoot application simply would not connect. The MongoDB instance would keep rejecting the authentication I gave to SpringBoot.

I tried countless changes to configs, including manually adding a mongo-init.js to create the database and user in Mongo. Which seemed counter to using the properties shown above.

Springboot configuration

There are a bunch of properties/annotations to setup in Springboot to allow auto configuration, but I'm not going to cover that. This is about why MongoDB suddenly started rejected the existing Springboot configuration.

After many hours of trying different ways of configuring my Springboot application and the Docker MongoDB config I stumbled across a comment on StackOverflow that was the magic I was missing.

?authSource=admin&authMechanism=SCRAM-SHA-1

One of the configuration options available to Springboot is to provide a connection URL rather than individual properties for host/user etc. I was using a series a properties that specified user/password/host/port. One of the changes I tried was to switch to use a single URL property to define the connection to my Mongo container.

Adding that little set of parameters to my connection  string and suddenly it's all sprung back to life. Hurrah!

Here is the relevant bits of my Springboot config that seems to work:

spring:
  security:
    filter:
      order: 10
  data:
    mongodb:
      uri: mongodb://mongoroot:pass12345@localhost/datastore?authSource=admin&authMechanism=SCRAM-SHA-1