Docker: Using docker-compose and networking to link a Spring Boot app to an external service dependency

In earlier versions of Docker,  links were used to connect two containers by enabling network access as well as sharing environment variables.  This approach is being deprecated in favor of a shared network between the services.  And instead of environment propagation, environment values will need to be explicitly added to each service that requires them.

In a previous article, I showed how to use Docker Compose to bring up a standalone Spring Boot based web application with in-memory persistence.  Now we expand on that idea by introducing an external MongoDB instance as the persistence store.  This MongoDB instance will come from a completely different docker-compose.yml file and will be  linked by virtue of a common network.

Prerequisites

Install Docker and docker-compose on your host machine, here are instructions for Ubuntu from one of my other articles.

In order to move forward with this article, run all the instructions in my previous article on Docker which includes installing Java and creating the executable spring-music.jar which is mandatory for the upcoming steps.

Run MongoDB from a Docker container

The first step is to run a MongoDB server from a docker container.  I more fully explain each step in my article here, but below is the abbreviated set of instructions.

First, grab my project from github.

$ sudo apt-get install git -y
$ git clone https://github.com/fabianlee/docker-mongodb.git
$ cd docker-mongodb

If you look at the snippet below of docker-compose.yml, you will see a named network “mongo_net“, and the “my-mongodb” service uses this network.

services:
  my-mongodb:
    image: mongo
  networks:
    - mongo_net

networks:
  mongo_net:
    driver: bridge

Now build and run using docker-compose to stand up the instance of MongoDB.

$ sudo docker-compose build
$ sudo docker-compose up -d
...
Creating network "docker-mongodb_mongo_net" with driver "bridge"
Creating my-mongodb ... done
Creating my-mongoclient ... done

Notice that the network created, “docker-mongodb_mongo_net” is the directory name followed by network name.  When we connect our Spring app to this service in the next step, this will be the network identifier.

Run Spring Boot app

In a previous article I stood up the spring-music app with docker-compose, but as a standalone app with in-memory persistence.  Now we will go through similar steps again, but this time with the file “docker-compose-mongo.yml” a snippet of which is shown below.

services:

  my-springmusic:
    image: my-springmusic
    build: .
    ports:
      - 8080:8080
    environment:
      # explicit profile required so that datasource is recognized and non-local
      - SPRING_PROFILES_ACTIVE=mongodb,remote
      # standard spring data property
      - spring.data.mongodb.uri=mongodb://admin:admin@my-mongodb:27017/test
    volumes:
      - javatmp:/tmp
    networks:
      - docker-mongodb_mongo_net

volumes:
  # default dir /var/lib/docker/volumes
  javatmp:

networks:
  docker-mongodb_mongo_net:
    external: true

docker-mongodb_mongo_net” was created when we instantiated the MongoDB instance earlier, and is the one we refer to here.  It must be marked as “external: true”.

Also see that we must explicitly provide environment variables that tell our application how to connect to MongoDB.  In the “spring.data.mongodb.uri” environment variable we are able to refer to “my-mongodb” as the name of the MongoDB server because the shared network makes this DNS resolution possible.

Now bring up the spring-music container with the commands below.

$ sudo docker-compose -f docker-compose-mongo.yml build
$ sudo docker-compose -f docker-compose-mongo.yml up
...
my-springmusic_1 | 2018-05-26T12:30:36.218+0000 INFO main o.c.s.m.Application:597 [log_framework=logback;app_name=spring-music;app_version=1.0;instance_id=0] The following profiles are active: mongodb,remote,mongodb-remote MULTIEXCEPTION
...
my-springmusic_1 | 2018-05-26T12:30:41.341+0000 INFO main o.c.s.m.Application:57 [log_framework=logback;app_name=spring-music;app_version=1.0;instance_id=0] Started Application in 5.629 seconds (JVM running for 5.976) MULTIEXCEPTION

Similar to the log entries above, you should see that the mongodb Spring profile is active and a JVM startup message.

Validate Application

Pointing your browser at http://127.0.0.1:8080 should show you the web interface similar to below with a listing of albums.

Try changing one of the album names, and then Ctrl-C to stop the spring-music container.   This stops the Spring Boot application (not the MongoDB database).  When you restart the web application with the command below all you changes should remain intact.

$ sudo docker-compose -f docker-compose-mongo.yml up

If you were using in-memory persistence, you would get a fresh start every time and none of your changes would survive a restart.

 

REFERENCES

https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.core-concepts

https://spring.io/guides/gs/accessing-data-mongodb/

https://stackoverflow.com/questions/23515295/spring-boot-and-how-to-configure-connection-details-to-mongodb

https://docs.spring.io/spring-data/mongodb/docs/1.2.0.RELEASE/reference/html/mongo.repositories.html

https://www.mkyong.com/spring-boot/spring-boot-spring-data-mongodb-example/

https://docs.docker.com/compose/compose-file/#external_links

https://springframework.guru/configuring-spring-boot-for-mongo/

 

NOTES

Delete spring app and its volume

sudo docker-compose -f docker-compose-mongo.yml down -v

Delete mongodb and its volume

sudo docker-compose down -v