Can't up my Eureka Spring REST service in a Docker container - rest

My project consists of a REST service, which is registered in Eureka, also I use Zuul proxy to manage requests as seen in this image. It runs perfectly on my computer in a local way but when I create a docker container for my service, it doesn't start. The steps I followed:
I created a Docker container for each service: Eureka server, Zuul API Gateway, the REST service and my Mysql database.
I get the data of my service from a stored procedure in the database, this conection was tested and it works.
I start all instances with docker-compose, Eureka and database instances remains up but the REST service instance stops abruptly. Zuul not is implemented yet.
The error:
matriculas-ms_1 | org.springframework.context.ApplicationContextException: Failed to start bean 'org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.eurekaClient' defined in class path resource [org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.netflix.discovery.EurekaClient]: Factory method 'eurekaClient' threw exception; nested exception is java.lang.RuntimeException: Failed to initialize DiscoveryClient!
Here is the docker-compose.yml
version: '3.3'
services:
srclbd:
build: ./srclbd
ports:
- "3307:3306"
expose:
- "3306"
volumes:
- ./srclbd/data:/var/lib/mysql
eureka:
build: ./Eureka
ports:
- "8761:8761"
expose:
- "8761"
matriculas-ms:
build: ./matriculas-ms
ports:
- "3333:3333"
expose:
- "3333"
depends_on:
- srclbd
- eureka
links:
- srclbd
- eureka
environment:
- DATABASE_HOST=srclbd
- EUREKA_HOST=eureka
Eureka's Dockerfile:
FROM java:8
ADD /target/eureka-0.0.1-SNAPSHOT.jar eureka-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java","-jar","eureka-0.0.1-SNAPSHOT.jar"]
REST service Dockerfile:
FROM java:8
ADD /target/matriculas-service-0.0.1-SNAPSHOT.jar matriculas-service- 0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java","-jar","matriculas-service-0.0.1-SNAPSHOT.jar","-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"]
Here is my project on github
Which is my error?

Finally I solved my error setting up a separated configuration profile to Docker container like this:
spring:
profiles: container
application:
name: matriculas-ms
jpa:
hibernate:
ddl-auto: none
datasource:
url: jdbc:mysql://srclbd:3306/srcl?useSSL=false&noAccessToProcedureBodies=true
username: root
password: root
initialize: true
eureka:
client:
serviceUrl:
defaultZone: http://eureka:8761/eureka/
server:
port: 1111
Then, I established this profile in the Dockerfile created to my REST service. So, every time it executes the JAR file, it will with the created profile's configuration.
FROM java:8
ADD /target/svcMatriculas.jar svcMatriculas.jar
ENTRYPOINT ["java","-Dspring.profiles.active=container","-jar","svcMatriculas.jar"]
Thanks!

Related

Unable to connect to the mongodb instance running in a docker container from inside the container

I have built a docker container consisting of a mongodb database and an azure http-triggered function. The following yaml is the docker compose file:
version: '3.4'
services:
mongo:
image: mongo
container_name: mongodb
restart: always
ports:
- 37017:27017
storage.emulator:
image: "mcr.microsoft.com/azure-storage/azurite:latest"
container_name: storage.emulator
ports:
- 20000:10000
- 20001:10001
- 20002:10002
my.functions:
image: ${DOCKER_REGISTRY-}myfunctions
build:
context: .
dockerfile: domain/My.Functions/Dockerfile
ports:
- 9080:80
depends_on:
- storage.emulator
- mongo
The mongodb instance runs well and I am able to connect to it from outside of the container by mongodb://localhost:37017 connection string to seed some data.
The Azure Function running inside the container is supposed to communicate with the mongodb instance by mongodb://localhost:27017 connection string but it fails according to the following error message:
"Unspecified/localhost:27017", ReasonChanged: "Heartbeat", State:
"Disconnected", ServerVersion: , TopologyVersion: , Type: "Unknown",
HeartbeatException: "MongoDB.Driver.MongoConnectionException: An
exception occurred while opening a connection to the server.
my.functions_1 | ---> System.Net.Sockets.SocketException (99):
Cannot assign requested address
How can I address this problem? Why the mongodb is unavailable internally to the azure function within the same container?
Because docker containers runs on isolated networks of their own. So when you try to connect localhost, actually you are trying to my.functions app and obviously it does not have service running on that part.
You should use docker-compose service name
mongodb://mongo:27017

Docker Compose - Service name not working as environment variable

I'm trying to use docker-compose to setup a Spring Cloud project.
I'm using spring cloud configuration so I have a Configuration Server and some services.
For now, I have 3 services in my docker-compose.yml
version: '3'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
MYSQL_USER: 'user'
MYSQL_PASS: 'password'
MYSQL_ROOT_HOST: '%'
volumes:
- "db:/opt/mysql/docker:rw"
ports:
- "3307:3306"
config:
image: config-server
restart: always
depends_on:
- db
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/ec_settings?createDatabaseIfNotExist=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
ports:
- "8100:8100"
gateway:
image: gateway
restart: always
depends_on:
- config
environment:
- CONFIG_URI=http://config:8100
ports:
- '8081:8080'
volumes:
db: {}
In gateway microservice, in bootstrap.yml, i have this setting
spring:
cloud:
config:
uri: ${CONFIG_URI}
When i put up the docker composer i see that gateway service is trying to fetch configuration from http://config:8100
Fetching config from server at : http://config:8100
So, the variable passes to Spring Boot but docker-compose does not replace the service name with its actual link.
The very strange thing is that SPRING_DATASOURCE_URL environment variable gets translated correctly in config service to connect to db service.
I finally solved it thanks to this link Docker - SpringConfig - Connection refused to ConfigServer
The problem was the service was trying to fetch the config url too early.
Solution is to put in bootstrap.yml this settings
spring:
cloud:
config:
fail-fast: true
retry:
max-attempts: 20

Accessing postgres data in docker-compose network

I'm having trouble accessing a database created from a docker-compose file.
Given the following compose file, I should be able to connect to it from java using something like:
jdbc:postgresql://eprase:eprase#database:7000/eprase
However, the connection is rejected. I can't even use PGAdmin to connect it using the same details to create a new server.
I've entered the database container and ran psql commands to verify that the eprase user and database have been created according to postgres Docker documentation, everything seems fine. I can't tell if the problem is within the database container or something I need to change in the compose network.
The client & server services can largely be ignored, the server is a java based web API and the client is an Angular app.
Compose file:
version: "3"
services:
client:
image: eprase/client:latest
build: ./client/eprase-app
networks:
api:
ports:
- "5000:80"
tty: true
depends_on:
- server
server:
image: eprase/server:latest
build: ./server
networks:
api:
ports:
- "6000:8080"
depends_on:
- database
database:
image: postgres:9
volumes:
- "./database/data:/var/lib/postgresql/data"
environment:
- "POSTGRES_USER=eprase"
- "POSTGRES_PASSWORD=eprase"
- "POSTGRES_DB=eprase"
networks:
api:
ports:
- "7000:5432"
restart: unless-stopped
pgadmin:
image: dpage/pgadmin4:latest
environment:
- "PGADMIN_DEFAULT_EMAIL=admin#eprase.com"
- "PGADMIN_DEFAULT_PASSWORD=eprase"
networks:
api:
ports:
- "8000:80"
depends_on:
- database
networks:
api:
The PostgreSQL database is listening on container port 5432. The 7000:5432 line is mapping host port 7000 to container port 5432. That allows you to connect to the database on port 7000. But, your services on a common network (api) should communicate with each other via the container ports.
So, from the perspective of the containers for the client and server services, the connection string should be:
jdbc:postgresql://eprase:eprase#database:5432/eprase

Docker compose: using relative service address in environment

For example, I defined two services in my docker-compose
backend:
env_file:
- .env.backend
build:
context: .
dockerfile: Dockerfile
ports:
- "8686:8686"
frontend:
env_file:
- .env.front_end
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
In frontend app, I defined environment with this endpoint:
BACKEND_ENDPOINT=http://www.backend.com/api/v1/backend/
The problem I don't know how to solve here is: how can I convert above endpoint to relative endpoint based on backend service. For example, if you run only backend under localhost, url should be: localhost:8686/api/v1/backend. So the url of backend in above docker-compose file should be: [backend_address]:8686/api/v1/backend. So how can I map address and port automatically here.
Thanks
With docker-compose, all services are always resolvable by their names.
In your example, you should add a depends_on from your frontend to your backend, and simply use the name backend to address the backend server.
frontend:
depends_on:
- 'backend'
The frontend should be able to resolve the backend at backend:8086. Note that the depends_on isn't required for name resolution, but it is required to ensure that the port is open when your frontend container is created.

Spring Boot with MongoDB on Docker

In these days, I am trying to deploy my Spring Boot OAuth2 project. It has 3 different modules.(Authentication Server, Resource Server and Front-end)
Authentication and Resource servers have own *.yml file for configurations such as mongodb name-port, server profile-ip etc.
What I am trying to do exactly? I want to deploy spring boot application on docker but i dont want to put my database(mongodb) on docker as a container.
I am not sure this structure is possible or not ?
Because When i run my mongodb on my local(localhost:27017) after that try to deploy spring boot application on local docker as a container, i am getting Timeout exception for MongoDB. The application couldnt connect to external mongoDB(non docker container).
What should I do? Should I run mongodb on docker? I tried it also, Mongo runs successfully but still spring container couldnt run and connect to mongo.
I tried to run another spring boot app without mongodb, it is working successfully and i made request from browser by ip&port, i got response from application as i expected.
*** MONGO URL ****
mongodb://127.0.0.1:27017/db-localhost
**** Authentication server .yml file ****
server:
port: 9080
contextPath: /auth-service
tomcat:
access_log_enabled: true
basedir: target/tomcat
security:
basic:
enabled: false
spring:
profiles:
active: development
thymeleaf:
cache: false
mongo:
db:
server: 127.0.0.1
port: 27017
logging:
level:
org.springframework.security: DEBUG
---
spring:
profiles: development
data:
mongodb:
database: db-localhost
---
spring:
profiles: production
data:
mongodb:
database: db-prod
---
***** DOCKER FILE *******
FROM java:8
VOLUME /tmp
ADD auth-server-1.0-SNAPSHOT.jar app.jar
EXPOSE 9080
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
**** DOCKER COMMAND *******
docker run -it -P --name authserver authserver
The issue with your configuration is referencing the mongodb from inside of the authservice on 127.0.0.1 which is the loopback adapter inside of the authservice container. So you tell your spring application that mongodb is running in the same container as the authservice spring application, which is not the case.
Either you are running your database as an own container (which requires to handle the data volumes correctly) and referencing it using the container name as hostname (via link) or you need to reference the externally running mongodb instance with the correct address. This would be the ip address of the machine running the docker daemon (I assume for your local environment something like 192.168.0.xxx).
Question: What should I do?
At least for developing purposes I would recommend to also use docker for your mongodb instance. I had a similar setup with RabbitMQ in addition and it solved a lot of problems when I used docker for those as well. Using docker-compose to set everything up makes it even easier. Later you can still specify which mongodb instance you want to use through your spring properties.
Problem: I tried it also, Mongo runs successfully but still spring container couldnt run and connect to mongo
The problem is probably because you have not set up any networks or hostnames for you services. Your spring application can not resolve the hostname of your mongo server, since you specified 127.0.0.1 for your mongodb server in your properties.
I would recommend using docker for your mongodb and use a docker-compose.yml file like this to set everything up:
version: '3.7'
services:
resource-server:
image: demo/resource-server:latest
container_name: resource-server
depends_on:
- mongodb-example
networks:
- your-network
ports:
- 8080:8080
auth-server:
image: demo/auth-server:latest
container_name: auth-server
depends_on:
- mongodb-example
networks:
- your-network
ports:
- 8081:8080
mongodb-example:
image: mongo:latest
container_name: mongo-example
hostname: mongo-example
networks:
- your-network
ports:
- 27017:27017
networks:
your-network:
name: network-name
Of course you then need to adapt your property file or specify environment variables through your docker-compose.yml file.