Springboot and Mongo containers are not connecting - spring

I'm running 2 containers on my local machine using docker compose. The first one is mongo container and the second is spring boot application.
This is my spring boot's Dockerfile
VOLUME /tmp
ADD target/app.jar app.jar
EXPOSE 8080
RUN bash -c "touch /app.jar"
ENTRYPOINT ["java","-Dspring.data.mongodb.uri=mongodb://mongo/test", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
This is my spring boot's application properties
# mongodb configuration0
dockerspring.data.mongodb.uri= mongodb://mongo:27000/test
This is my docker-compose.yml
version: '3.1'
services:
level-2-springboot:
image: level-2:latest
restart: always
container_name: level_2_microservice
ports:
- 8081:8080
working_dir: /tmp
depends_on:
- mongo
mongo:
image: mongo
container_name: mongo
ports:
- 27000:27017
restart: always
This is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yash</groupId>
<artifactId>spring-sync-ms</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-sync</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>app</finalName>
</build>
</project>
I execute this to create image for my spring boot app
docker build -t level-2 .
After I see my image, I execute docker-compose up and they work just fine no error
Here is the containers running
But when i do a POST or GET request to localhost:8081/api/employees/ or localhost:8080/api/employees/ I'd get this message from Postman
Could not get any response
Below is my project structure
If I run the app on eclipse and mongo manually and do POST/GET request, I'd get 201 OK, but when I do it using docker in containers, they dont talk to each other. Anyone know whats causing this?

I've consulted the internet and i think i got what you need.
The question that follows is “how does our service container talk to
the Mongo container?” For that, we get into container linking.
When you run a container, you can pass an optional –link parameter,
specifying the running container name that the new container needs to
be able to communicate with.
So with our command
docker run -P -d --name employee --link mongodb microservicedemo/employee
we fire up our new container image, exposing its ports (-P) in the background
(-d), naming it employee (–name), and telling it to link to the
container named “mongodb” (–link). Linking these does the following:
Creates a hosts file entry in the employee container pointing at the
running location of the MongoDB container Inserts a number of
environment variables in the employee container to assist with any
other programmatic access needed.
To see them run: docker exec employee bash -c 'env |grep MONGODB'
Allows containers to communicate directly over ports exposed, so there is no need to
worry about the hose machine part mapping.
see:
https://www.3pillarglobal.com/insights/building-a-microservice-architecture-with-spring-boot-and-docker-part-iii
https://www.3pillarglobal.com/insights/building-a-microservice-architecture-with-spring-boot-and-docker-part-ii

This:
# mongodb configuration0
dockerspring.data.mongodb.uri= mongodb://mongo:27000/test
Should be:
# mongodb configuration0
dockerspring.data.mongodb.uri= mongodb://mongo:27017/test
The two services in your docker-compose.yml expose Ports 8081 and 27000 to the host machine.
But inside the network created by docker-compose they expose Ports 8080 and 27017.
As your Mongo-Container runs in the docker-compose network, it has to use Port 27017 to connect to the database.

Related

Deploy Spring Boot application on AWS (Elastic Beanstalk) that uses RDS - Application does not start

I have a SpringBoot application connected to a MySQL database. This has already been installed on AWS and entered into Spring's properties file. The connection works and I can also connect to it with my workbench. But my problem is that the application does not run on AWS. I changed the SERVER_PORT to 5000 (also in the properties) but I can't get the APP to run
The AWS log file:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.backend</groupId>
<artifactId>SYFALL</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SYFALL</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties file:
server.port = 5000
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
spring.datasource.url = jdbc:mysql://AWS_DATABASE:3306/syfall
spring.datasource.username = xxx
spring.datasource.password = xxx
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
The application was built as a JAR file.
As stated in the comments, I have my sample Spring BOOT app that uses MySQL RDS data and queries and displays data perfectly.
I am currently in the process of deploying to Elastic Beanstalk. I will update this thread with notes once done.
UPDATE
I successfully deployed this Spring BOOT app to Elastic Beanstalk and got the RDS Connection working. I packaged up the Spring BOOT app into a JAR by using mvn package. Then I deployed the JAR onto Elastic Beanstalk.
Notes:
Be sure to specify your environment variables correctly in the Elastic Beanstalk environment (as opposed to a Spring config file) -- as shown here:
The AWS Creds are needed if your app uses an AWS Service Client. I use SES in this app so I need them
Now here is the important part. You need to set the Inbound rules so that a connection from the app deployed on EB to RDS can be made. I simply used this for testing....
To take this further, you can of course use the IP Address of your app on Beanstalk in your Inbound Rule. To do so, get the IP of your Elastic Beanstalk app. Then use that IP in your inbound rule.
Make sure that the Security Group your RDS uses is also the same Security Group your EB app uses. Both RDS and EB has to be in same region.

Traefik throwing error 502 with Kotlin Spring Boot application

Ok so I'm facing an annoying issue with Traefik in Docker: it constantly throws an error 502: Bad Gateway when I'm trying to reach my HTTP service.
All I'm trying to do is add it as a simple load balancer to build 3 replicas of my Spring Boot app. The app works well when I remove anything concerning Traefik.
My Spring Boot Controller maps /api/v1 endpoint, which is working well without load balancing. I'm trying to map this same endpoint to Traefik, which is using port :80.
Dashboard at :8080 works just fine, I have no error whatsoever about my configuration mentioned in it; only problems when I'm reaching anything under :80.
I have to mention that this exact same configuration (docker-compose, traefik conf, postgres db, and spring boot app) DOES WORK fine with the exact same docker-compose.yml AND traefik.yml, which makes my problem even weirder. Maybe the issue comes from the fact that my Spring Boot app is made of Kotlin and not the one where it's working?. Anyway, here are my files:
# Dockerfile (default one generated)
FROM maven:latest
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN mvn package
ENV PORT 5000
EXPOSE $PORT
CMD [ "sh", "-c", "mvn -Dserver.port=${PORT} spring-boot:run" ]
# docker-compose.yml (works as-is in my other app)
version: "3.8"
services:
project:
build: .
deploy:
replicas: 3
labels:
- "traefik.http.routers.project.rule=PathPrefix(`/api/v1`)" # same endpoint as in my Spring controller
- "traefik.http.middlewares.project.stripprefix.forceSlash=false"
- "traefik.http.routers.project.middlewares=project#docker"
traefik:
image: traefik:latest
restart: unless-stopped
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.yml:/etc/traefik/traefik.yml
postgres:
image: postgres:latest
container_name: postgres
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: example
# rabbitmq:
# image: rabbitmq:management-alpine
# container_name: rabbitmq
# ports:
# - "5672:5672" # AMQP
# - "15672:15672" # HTTP (Management)
# traefik.yml
global:
checkNewVersion: true
sendAnonymousUsage: false
providers:
docker: {}
log:
level: DEBUG # temporarily
api:
insecure: true
entryPoints:
insecure:
address: ":80"
secure:
address: ":443"
# src/main/resources/application.yml
spring:
sql.init.mode: always
datasource:
url: jdbc:postgresql://localhost:5432,postgres:5432/postgres
username: postgres
password: example
jpa:
open-in-view: false
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<kotlin.version>1.6.10</kotlin.version>
</properties>
<dependencies>
<!-- Kotlin -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
I'm using JDK 17, and docker-compose up --build to start everything. Thanks!

PCF Unable to use Config Server and Service Registry together in an Application

I am trying to bind the PCF Config Server and PCF Service registry in the same Application and push the app . However I get an error while the application is starting . The problem is due to the application unable to send the Hertbeat information and it fails with unable to refresh cache.
If i bind config server alone and Service registry alone it works but when both the services are bound it fails.
Any help with this is appreciated
The dependencies are as follows
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>io.pivotal.spring.cloud</groupId>
<artifactId>spring-cloud-services-starter-service-registry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.pivotal.spring.cloud</groupId>
<artifactId>spring-cloud-services-starter-config-client</artifactId>
</dependency>
This was resolved after gave the Service registry to take the path using the following configuration
spring.cloud.services.registrationMethod=route

Missing AWS properties when creating AWS application

I'm struggling to figure out how to add AWS properties to my application.properties (or application.yml) file, and I'm not sure what I have set up incorrectly in STS.
I can reproduce this creating a simple AWS app using Spring Initializr. I'm adding AWS, Consul and REST because that's what the real app is using. Here's the POM it generates.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.dkist</groupId>
<artifactId>staging-service-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>staging-service-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.SR4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I'm not adding any code to the application for this sample, only the code that is generated. This was a test to see if something was wrong with the app I was working on. When I try to add an application property, nothing shows for AWS. The same is true if I create a YAML file.
If I force the issue, and add it anyway STS says the property is unknown.
Compiling the app throws an exception:
Caused by: java.lang.IllegalStateException: There is not EC2 meta data available, because the application is not running in the EC2 environment. Region detection is only possible if the application is running on a EC2 instance
The app is not running on an EC2 instance, it's running locally. From what I've read I need to add the aws.region.auto if it's not running on EC2, but I can't get the app to acknowledge the property exists. Same happens with the access key and secret key.
So... after lots of tinkering and reading other posts it looks like the properties will work if you add them, even if STS doesn't recognize them.
I added
cloud:
aws:
credentials:
instanceProfile: false
region:
static: eu-west-1
stack:
auto: false
and the program will run.
The other thing that was tripping me up is the inconsistency in the paths for the properties. For example Consul properties are at
spring.cloud.consul.*
where as AWS is at
cloud.aws.*
There's no "spring" to start the AWS properties. I'm sure there is a reason for the inconsistency, I just don't know it.

Running Spring Clound Config and Eureka on same server

We are trying to create a dashboard for our application as a single point of entry/configuration. For this we will build and UI and would like to run Spring Cloud Config and Eureka on same instance. Is there any reason why we should not do this and if not is it possible?
#mvlupan, there is nothing keeping you from using together. That is one of the reasons we created #EnableEurekaServer and #EnableConfigServer.
pom.xml snippet.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
Application.java snippet
#EnableEurekaServer
#EnableConfigServer
#SpringBootApplication
public class DemoconfigandeurekaserverApplication { /*...*/}
application.properties snippet (so eureka and config server don't clash).
spring.cloud.config.server.prefix=/config
For high availability in production environment there should be at least 2 instances running on different servers.
Both ConfigServer and EurekaServer should have 2 instances.
Personally I prefer to see ConfigServer and EurekaServer running as one process as #spencergibb has shown.
There are config-first or discovery-first approches on what runs first.
P.S.
I expect that your Dashboard application will be separate from ConfigServer/EurekaServer,
so its own issues would not affect business critical parts.

Resources