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