Java app can't connect to rabbitMQ from the same docker container - java

I have a sample Spring Boot app that produce message:
#Scheduled(fixedRate = 10000)
public void test() throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello Rabbit!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
System.out.println(" [x] Sent '" + message + "'");
}
}
It is dockerized:
FROM openjdk:11 as jdkbase
FROM jdkbase
COPY target/RabbitMQtester-0.0.1-SNAPSHOT.jar /run/RabbitMQtester-0.0.1-SNAPSHOT.jar
#ADD target/sfida-1.0.0.jar /run/sfida-1.0.0.jar
ENTRYPOINT java -Dfile.encoding=UTF-8 -jar /run/RabbitMQtester-0.0.1-SNAPSHOT.jar
I need to build an image containing both RabbitMQ and my app. Here is docker-compose.yml for this task:
version: "3.7"
services:
mytestapp:
build: .
rabbitmq:
image: rabbitmq:3.8.3-management-alpine
hostname: localhost
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- 5672:5672
- 15672:15672
When i start the resulting image, i can access rabbitMQ admin page from my host. Also, i can run my app from the host and it'll access rabbitMQ.
But my app, which is in the container/image, can't access RabbitMQ (it throws "Connection refused (Connection refused)" errors)
What is wrong with my configurations?
UPD: I've also tried to change docker-compose.yml to this (and connection in my app to factory.setHost("rabbitmq"); )
version: "3.8"
services:
mytestapp:
build: .
networks:
- some-net
rabbitmq:
image: rabbitmq:3.8.3-management-alpine
hostname: rabbitmq
networks:
- some-net
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- 5672:5672
- 15672:15672
networks:
some-net:
driver: bridge
and to this:
version: "3.8"
services:
mytestapp:
build: .
rabbitmq:
image: rabbitmq:3.8.3-management-alpine
hostname: rabbitmq
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- 5672:5672
- 15672:15672
but result is the same...

The RabbitMQ service is by default accessible using the name of the docker service rabbitmq (when you remove hostname: localhost) from other services in the same stack (provided they are configured with the same network, in this case the default). So you should replace factory.setHost("localhost"); with factory.setHost("rabbitmq"); and remove hostname: localhost.
You did specify hostname: localhost, so one could assume RabbitMQ can be accessed using localhost hostname from the mytestapp service, but since it's not working it's very likely conflicting with the default loopback and resolving to 127.0.0.1 instead.

Related

Connecting spring boot docker container to MQTT docker container

I'm trying to connect my containerized spring boot application with another containerized MQTT broker. Both of them are on their own projects as follows:
mqtt docker-compose.yml:
version: '3.9'
services:
mqttbroker:
container_name: mqttbroker
restart: always
volumes:
- ./config:/mosquitto/config
- ./data:/mosquitto/data
- ./log:/mosquitto/log
ports:
- 8883:8883
networks:
- mynetwork
volumes:
config:
data:
log:
mqtt Dockerfile
FROM eclipse-mosquitto
WORKDIR /mosquitto
COPY . .
EXPOSE 8883
And then the spring boot project is like:
spring boot docker-compose.yml
version: '3.8'
services:
myapp:
build: .
container_name: myapp
ports:
- '8082:8082'
stdin_open: true
tty: true
networks:
- mynetwork
In my application.properties I try to connect to the MQTT broker like:
mosquitto.url=tcp://mqttbroker:8883 and I get connection refused. However, if I run the spring boot application locally, I can connect to the docker container with mosquitto.url=tcp://localhost:8883.
I would rather have all the configurations in my docker-compose files to decrease manual codes.
I really appreciate your help in advance!
Yes, You do have to share the network as external.
you cab check the networks you have with this command : docker network ls
You would notice that they each have their own networks.
adding this to spring boot docker-compose file should fix the issue :
networks:
default:
name: mynetwork
external: true
For more information about docker compose networks

App container cannot connect to mysql container in the same network

I have a problem with the docker and containerized apps not connecting to mysql database that is running in a container within the same docker network. My docker-compose.yml looks like this:
version: '3.8'
services:
mysqlserver:
image: mysql:5.7.24
container_name: mysql_app
networks:
- somenetwork
ports:
- "5647:3306"
environment:
MYSQL_DATABASE: database
MYSQL_USER: USER
MYSQL_PASSWORD: PASS
MYSQL_ROOT_PASSWORD: PASS
command:
- --max_connections=1000
restart: always
volumes:
- persistent:/var/lib/mysql
app:
image: app/appserver:latest
container_name: app_server
networks:
- somenetwork
ports:
- "8080:8080"
depends_on:
- mysqlserver
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysqlserver:5647/database?verifyServerCertificate=false&useSSL=false&requireSSL=false&autoReconnect=true
networks:
somenetwork:
name:
somenetwork_share_net
volumes:
persistent:
And looking at the logs from the app container, I found errors like this:
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
and
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
Is there something wrong with my docker-compose.yml? Why the app container cannot connect
You have to use the exposed port on container side 3303 and not the public one 5647.
Just try
SPRING_DATASOURCE_URL: jdbc:mysql://mysqlserver:3306/database?verifyServerCertificate=false&useSSL=false&requireSSL=false&autoReconnect=true
The port in local network stays the original exposed port. In port section you just define the public ports on the host machine.

Docker Compose connect to external Postgres databases

I have a SpringBoot application that works perfectly. Now I am trying to Dockerise it, but have some issues when connecting to the database.
The application has two datasources:
application.properties
server.port= 8081
# pims datasource
spring.datasource1.driver-class-name=org.postgresql.Driver
spring.datasource1.jdbc-url=jdbc:postgresql://localhost:5432/pims
spring.datasource1.username=postgres
spring.datasource1.password=
spring.jpa.database-platform=postgres
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=false
# approval datasource
spring.datasource2.driver-class-name=org.postgresql.Driver
spring.datasource2.jdbc-url=jdbc:postgresql://localhost:5432/approval
spring.datasource2.username=postgres
spring.datasource2.password=
In the application, I use Spring to access the two datasources:
#Configuration
#ComponentScan(basePackages = "com.nexct")
public class MultipleDBConfig {
#Bean(name = "datasource1")
#ConfigurationProperties("spring.datasource1")
#Primary
public DataSource dataSource1(){
return DataSourceBuilder.create().build();
}
#Bean(name = "datasource2")
#ConfigurationProperties("spring.datasource2")
public DataSource dataSource2(){
return DataSourceBuilder.create().build();
}
}
So I have created:
Dockerfile
FROM openjdk:14
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} nexct-approval-service.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/nexct-approval-service.jar"]
docker-compose.yml
version: '3.7'
services:
product-service:
build: ../nexct-approval-service
volumes:
- ../nexct-approval-service:/usr/src/app
ports:
- "8081:8081"
db:
image: postgres
environment:
POSTGRES_DB_PORT: "5432"
POSTGRES_DB_HOST: "localhost"
POSTGRES_PASSWORD:
POSTGRES_USER: postgres
POSTGRES_DB: pims
However, I am not sure how to configure the two Postgres databases.
Any advise would be appreciated.
Note: the databases are not running in a container, as they are used by other legacy applications.
If I remove the db from docker-compose.yml. When I run docker-compose up, the Spring Boot application starts, and I can access a RESTful service. However, I get the following error:
PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
version: '3.7'
services:
product-service:
build: ../nexct-approval-service
volumes:
- ../nexct-approval-service:/usr/src/app
ports:
- "8081:8081"
server.port=8081
# pims datasource
spring.datasource1.driver-class-name=org.postgresql.Driver
spring.datasource1.jdbc-url=jdbc:postgresql://<postgres_host_private_ip>:5432/pims
spring.datasource1.username=postgres
spring.datasource1.password=
spring.jpa.database-platform=postgres
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=false
# approval datasource
spring.datasource2.driver-class-name=org.postgresql.Driver
spring.datasource2.jdbc-url=jdbc:postgresql://<postgres_host_private_ip>:5432/approval
spring.datasource2.username=postgres
spring.datasource2.password=
Replace <postgres_host_private_ip> with the private IP of the machine hosting the postgres databases.
I'm not sure what you were trying to achieve with the nested db service, but since your database are already running somewhere outside there is no need for this.
Your Spring application will run on a isolated network from your host because of the docker isolation (unless explicitly asked to use host network with network_mode: "host"). Knowing that, the "localhost" can not work inside the container, you need to use the real IP of the machine that hosts the databases. Most likely something like 192.168.xxx.xxx
Also, you need to make sure the postgres is configured to accept connection from "non-localhost" sources (see https://www.andrew-kirkpatrick.com/2017/05/allow-connection-postgresql-server-outside-localhost/).
To access an application running on ur Host there are few options
Use the Bridge network. (Doc)
Create a bridge network and assign the subnet address and gateway address.
Now you can reach your application running at the host from the container at <gateway address>:<port> i.e 172.28.0.1:<port>
version: '3.7'
services:
product-service:
build: ../nexct-approval-service
volumes:
- ../nexct-approval-service:/usr/src/app
ports:
- "8081:8081"
networks:
hostnet: {}
networks:
hostnet:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
Use Attach service to host network. (Doc)
add network_mode: host to your service (only works on Linux)
OR create an external network
Now you can reach your application running at the host from the container at localhost:<port>
With network_mode: (Linux)
version: '3.7'
services:
product-service:
build: ../nexct-approval-service
volumes:
- ../nexct-approval-service:/usr/src/app
ports:
- "8081:8081"
network_mode: host
Try configuring your docker-compose file to use bridged networking:
version: '3.7'
services:
product-service:
build: ../nexct-approval-service
volumes:
- ../nexct-approval-service:/usr/src/app
environment:
POSTGRES_DB_PORT: "5432"
POSTGRES_DB_HOST: "localhost"
POSTGRES_PASSWORD:
POSTGRES_USER: postgres
POSTGRES_DB: pims
networks:
- product_service_network
networks:
product_service_network:
driver: bridge
You also have to move the ENVIRONMENT variables to product-service if you are going to use them in the product-service container.
If localhost doesn't work, use 127.0.0.1 instead.

How to make Spring boot with Redis Sentinel work with Docker

I am trying to set up a Spring boot application with Redis Sentinel 3.2.11 using docker. However I am getting
Caused by: io.netty.channel.ConnectTimeoutException: connection timed out: /172.27.0.2:6379
My docker compose configuration
version: '3.1'
services:
master:
image: redis:3
container_name: redis-master
hostname: host_dev
networks:
- docker_dev
slave:
image: redis:3
command: redis-server --slaveof redis-master 6379
hostname: host_dev
links:
- master:redis-master
container_name: redis-slave
networks:
- docker_dev
sentinel:
build: sentinel
environment:
- SENTINEL_DOWN_AFTER=5000
- SENTINEL_FAILOVER=5000
- MASTER_NAME=mymaster
hostname: host_dev
image: sentinel:3
links:
- master:redis-master
- slave
container_name: sentinel
ports:
- "26379:26379"
networks:
- docker_dev
networks:
docker_dev:
Docker file
FROM redis:3
EXPOSE 26379
ADD sentinel.conf /etc/redis/sentinel.conf
RUN chown redis:redis /etc/redis/sentinel.conf
ENV SENTINEL_QUORUM 2
ENV SENTINEL_DOWN_AFTER 30000
ENV SENTINEL_FAILOVER 180000
COPY sentinel-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/sentinel-entrypoint.sh
ENTRYPOINT ["sentinel-entrypoint.sh"]
Spring configuration in application.properties:
redis.cluster.name=mymaster
redis.sentinel.nodes=localhost:26379
redis.timeout=2000
Issue:
The spring boot app(run from outside docker-machine) is able to connect with Sentinel node. The sentinel node provides the master information with IP 172.27.0.2 i.e docker n/w IP. The spring boot app tries to connect with redis-master at IP 172.27.0.2 and fails as the IP is not visible outside the docker machine.
Possible fix:
How can I make sentinel node provide an master IP as localhost instead of internal docker-machine n/w ip?

com.mongodb.MongoSocketOpenException: Exception opening socket(MongoDB, Docker)

I try to starting my application(Spring Boot + Spring Cloud + Eureka + MongoDB) with using docker image, but i can't get connection to MongoDB.
Exception:
exception "com.mongodb.MongoSocketOpenException: Exception opening socket."
I starting my application with execute command: docker-compose up --build
Docker log:
com.mongodb. MongoSocket0penException: Exception opening socket at com.mongodb. connection. SocketStream.open(SocketStream.java: 63) ~|mongo-java-driver-3.2.2.jar!/:naj
at com. monsoob: connection. berettaberverwontortser/ersonito-kunnablearancerainitservertonitolnava:1203-dionso-java-driver*3?2.2.jarl/:nal
at : java. lang. Thread.run (Thread. java: 745) Lna:1.8.0_111]
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect (Native Method) ~ [na: 1.8.0_1111 at java.net.AbstractPlainSocketImp1.doConnect (AbstractplainSocketImpl.java:350) ~ [na: 1.8.0_111]
at java.net.AbstractPlainSocketImp1.connectToAddress(AbstractPlainSocketImp1.java:206)~[na:1.8.0_1111
at java.net .AbstractPlainSocketImp1.connect (AbstractPlain5ocket Imp],java:188) ~[na:1.8.0_111]
at java.net.SocksSocketImpl.connect (SocksSocketImpl.java:392) ~|na:1.8.0_111] java.net Socket. connect (Socket, java: 589) ~[na:1.8:0-111]
at com.mongodb.connection. SocketStreamHelper.initialize(SocketStreamHelper. java: 50) ~ [mongo-java-driver-3.2.2.ar!/:na] at com. mongodb. connection. SocketStream.open(SocketStream. java:58) ~ [mongo-java-driver-3.2.2.jar!/:na]
3 common frames omitted
application.yml:
# Spring properties
spring:
application:
name: car-service
data:
mongodb.host: localhost
mongodb.port: 32769
mongodb.uri: mongodb://localhost/test
mongo.repositories.enabled: true
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
# HTTP Server (Tomcat) Port
server:
port: 2220
error:
whitelabel:
enabled: false
docker-compose.yml:
eureka:
build: ./eureka-discovery-service
ports:
- "8761:8761"
mongodb:
image: mongo:3.0.4
ports:
- "32769:32769"
postgresql:
image: postgres:9.6.1
ports:
- "32770:32770"
gateway-service:
build: ./gateway-service
ports:
- "9090:9090"
links:
- eureka
environment:
SPRING_APPLICATION_NAME: gateway-service
SPRING_PROFILES_ACTIVE: enableEureka
EUREKA_INSTANCE_PREFER_IP_ADDRESS: "true"
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka:8761/eureka/
airplane-service:
build: ./airplane-service
ports:
- "2222:2222"
links:
- eureka
- postgresql
environment:
SPRING_APPLICATION_NAME: airplane-service
SPRING_PROFILES_ACTIVE: enableEureka
EUREKA_INSTANCE_PREFER_IP_ADDRESS: "true"
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka:8761/eureka/
SPRING_SLEUTH_ENABLED: "true"
SPRING_DATASOURCE_POSTGRESQL_URL: jdbc:postgresql://localhost:32770/postgres
car-service:
build: ./car-service
ports:
- "2220:2220"
links:
- eureka
- mongodb
environment:
SPRING_APPLICATION_NAME: car-service
SPRING_PROFILES_ACTIVE: enableEureka
EUREKA_INSTANCE_PREFER_IP_ADDRESS: "true"
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka:8761/eureka/
SPRING_SLEUTH_ENABLED: "true"
SPRING_DATA_MONGODB_URI: mongodb://localhost:32769/test
machine-service:
build: ./machine-service
ports:
- "2224:2224"
links:
- eureka
environment:
SPRING_APPLICATION_NAME: machine-service
SPRING_PROFILES_ACTIVE: enableEureka
EUREKA_INSTANCE_PREFER_IP_ADDRESS: "true"
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka:8761/eureka/
SPRING_SLEUTH_ENABLED: "true"
Why I have exception opening a socket? How to fix this problem?
You are setting mongodb host in property file as localhost. In a container localhost address itself, but your mongodb is not in that container(car-service) which car-service run in. While you are using docker compose, you can address a container with its name. In your case it is mongodb.
to clarify #barbakini's answer, to define it in applications.yaml use:
spring.data.mongodb.host: mongodb
Your mongoDB service is not UP ,
Check the status by following command
sudo service mongodb status
sudo service mongodb start
Hope it should work, there could be several reasons as well ,
like the configuration you defined in your application for mongodb service is incorrect such as port .
Try to add
network_mode: host
and remove
links: ....
for all services, that want to connect with mongo or eureka or postgresql, inside your docker-compose.yml.
By doing so you will connect to docker localhost.

Categories