Connecting dockerized Spring boot app to MQTT Mosquitto broker - spring-boot

hope someone can help me with this issue.
I have an app running with docker called "my-app". It connects to a MQTT Mosquitto broker which is also running in a docker container. Here is the docker-compose file:
mosquitto:
container_name: mosquitto
image: eclipse-mosquitto:2.0.14
ports:
- 1883:1883
- 9001:9001
volumes:
- "./mosquitto/Broker.conf:/mosquitto/config/mosquitto.conf"
- "./mosquitto/Password:/mosquitto/config/mosquitto.passwd"
my-app:
container_name: my-app
image: data-provider:latest
ports:
- 8080:8080
depends_on:
- mosquitto
networks:
- my-app-network
I have a configuration file for the broker with the following:
listener 1883
password_file /mosquitto/config/mosquitto.passwd
allow_anonymous false
Looking at the mosquitto container log files, I can see it starts without erros when running docker-compose.
1658337045: mosquitto version 2.0.14 starting
1658337045: Config loaded from /mosquitto/config/mosquitto.conf.
1658337045: Opening ipv4 listen socket on port 1883.
1658337045: mosquitto version 2.0.14 running
However, my Java app is unable to connect with the mosquitto broker. Whenever I try to send a message to be published, I receive the following error:
Caused by: org.springframework.messaging.MessagingException: Failed to connect; nested exception is MqttException (0) - java.net.UnknownHostException: mosquitto
The Java code is the following:
#Value("${mqtt.url}")
private String url;
#Bean
public MqttPahoClientFactory mqttClientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
options.setServerURIs(new String[] { url });
...
...
return factory;
}
In the properties file:
mqtt.url = tcp://mosquitto:1883
If I try to run the app with an embedded tomcat server, and I change the url to localhost:1883, then everything will work fine:
1658338620: New connection from <ip>:59730 on port 1883.
1658338621: New client connected from <ip>:59730 as my-app.topic (p2, c1, k60, u'admin').
I think I'm not exposing the docker host container URL in the correct way, but I have tried a few configurations without success. Does anyone know what I'm doing wrong and what I need to change in my broker config?
PS: I'm using spring-integration-mqtt 5.5.10
Thanks in advance!

Currently you mosquitto service is on the Bridge network and my-app is on the my-app-network. Hence they are unable to talk to each other. You need to bring both the services under one network.
mosquitto:
container_name: mosquitto
image: eclipse-mosquitto:2.0.14
ports:
- 1883:1883
- 9001:9001
volumes:
- "./mosquitto/Broker.conf:/mosquitto/config/mosquitto.conf"
- "./mosquitto/Password:/mosquitto/config/mosquitto.passwd"
networks:
- my-app-network

Related

Error Connecting to server(111): Connection refused when using RabbitMQ in Laravel

I have 2 services written in Laravel. I'm trying to develop my projects with Docker Compose.
one of my services has the below configuration for rabbitMQ in the docker-compose.yml file:
rabbitmq:
image: rabbitmq:3-management-alpine
container_name: 'product_rabbitmq'
ports:
- 5672:5672
- 15672:15672
volumes:
- ~/.docker-conf/rabbitmq/data/:/var/lib/rabbitmq/
- ~/.docker-conf/rabbitmq/log/:/var/log/rabbitmq
environment:
- RABBITMQ_DEFAULT_USER=root
- RABBITMQ_DEFAULT_PASS=password
for the second service, I can't use the same port, so I'm changing the port to 5671 or 4000 as the below:
ports:
- 5671:5672
- 15673:15672
But I'm getting the Error Connecting to server(111): Connection refused error.
everything is OK when I shut down the service1 and expose rabbitMQ on port 5672.
also, I have changed my .env file.
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5671
RABBITMQ_USER=root
RABBITMQ_PASSWORD=password
Should I choose another port?

RabbitMQ not working when services are dockerized

So I have 2 services. Kweet (which is a tweet) and User. When I run the 2 services manually + rest of the services in docker, it works. Rest of services include MongoDB, RabbitMQ, Spring Cloud Gateway, Eureka Discovery. But the moment I run the 2 (micro)services in Docker (I just use a docker compose), the rabbitmq functionality stops working. The normal API calls work, it's specifically the RabbitMQ calls that fail.
RabbitMQ functionality:
EditUsername, edits username in user-service.
Than sends data via RabbitMQ (this is where it goes wrong I think) to kweet-service where it edits the username of a kweet.
Docker-compose file:
version: '3.8'
services:
eureka-service:
build: ./eureka-discovery-service
restart: always
container_name: eureka-service
ports:
- 8087:8087
api-gateway:
build: ./api-gateway
restart: always
container_name: api-gateway
depends_on:
- eureka-service
ports:
- 8080:8080
user:
build: ./user
restart: unless-stopped
container_name: user-ms
ports:
- 8081:8081
depends_on:
- eureka-service
kweet:
build: ./kweet
restart: unless-stopped
container_name: kweet-ms
depends_on:
- eureka-service
ports:
- 8082:8082
mongodb:
image: mongo
restart: always
container_name: mongodb
ports:
- 27017:27017
rabbitmq:
image: rabbitmq:management
restart: always
container_name: rabbitmq
hostname: rabbitmq
ports:
- 5672:5672
- 15672:15672
When I try to make a call the console shows:
user-ms | 2022-04-27 08:52:04.823 INFO 1 --- [nio-8081-exec-4] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [localhost:5672]
The postman status I get back is 503 Service Unavailable which isn't from any try-catch's I made. Anybody have any clue where the problem might be?
EDIT[ConnectionFactory]:
I tried to use the documentation and added a the CachingConnectionFactory but it had the same result. Am I doing it wrong?
I added this to the RabbitMQ/Message-config (HOST, USERNAME, PASSWORD come from application.properties:
#Bean
public AmqpTemplate template() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(HOST);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(converter());
return rabbitTemplate;
}
EDIT [docker-compose]:
Found this source (https://www.linkedin.com/pulse/binding-your-docker-app-container-rabbitmq-phani-bushan/) that got rid of my 503 Service Unavailable error. The problem I found now is that whenever I start up the containers, it generates new queues and exchanges that aren't the ones I set up in my application.properties.
Now whenever I make a call, it shows this log:
user-ms | 2022-04-28 07:36:28.825 INFO 1 --- [nio-8081-exec-1] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#2ca65ce4:0/SimpleCo
nnection#7e7052f [delegate=amqp://guest#172.23.0.4:5672/, localPort= 43208]
Things tried:
change host to [rabbitmq-container-name] in code via CachingConnectionFactory
change host to [rabbitmq-container-name] in docker compose with environment: - spring_rabbitmq_host=[rabbitmq-container-name]
build: ./user
restart: unless-stopped
container_name: user-ms
depends_on:
- eureka-service
- rabbitmq
ports:
- 8081:8081
environment:
- spring_rabbitmq_host=[rabbitmq-container-name]
Instead of [rabbitmq-container-name] I've tried host.docker.internal and localhost
When you dockerize your services are no longer listening in localhost. If you need to network connect services you need to use container_name instead of localhost.
localhost points to the container itself, where only one service is listening. Do not mistake for when you develop on your laptop without containers, where everything is in localhost
More about this here
By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
You must configure, somewhere in your user-ms application (we do not know what kind of applicatin is), that RabbitMQ service is listening at rabbitmq (container_name) not localhost.
Try to use the container with environment variables. For me it is enough for working.
rabbitmq:
image: rabbitmq:management
restart: always
container_name: rabbitmq
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
RABBITMQ_DEFAULT_VHOST: /
ports:
- 5672:5672
- 15672:15672
I can open this container in a browser: http://localhost:15672/
I use PHP FPM and Symfony and I pass env value to this container to connect to rabbitmq.
services:
php-fpm:
environment:
ENQUEUE_DSN: amqp://guest:guest#rabbitmq:5672
For Java you need to find and define or redefine application properties. The config may use the default value for localhost, like this spring.rabbitmq.host=localhost, but you need to use Docker's host, it is rabbitmq.
spring.rabbitmq.host=rabbitmq
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
I have made a grave mistake. 2 things that I did before it started working.
Change Dockerfile ADD command to COPY (Don't think that was the problem though)
Deleted all my images and containers and re-made them a.k.a instead of docker-compose up I should've been typing docker-compose up --build. This was most likely the issue
brb gonna cry in a corner

Hosted Service RabbitMQ connection failure using Docker Compose

Here is the log
MassTransit.RabbitMqTransport.Integration.ConnectionContextFactory.CreateConnection(ISupervisor supervisor)
[02:51:48 DBG] Connect: guest#localhost:5672/
[02:51:48 WRN] Connection Failed: rabbitmq://localhost/
RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the specified endpoints were reachable
The RabbitMQ control panel is showing the exchanges and queues as created and when I make a publish request I see the queue come through but then get a MassTransit timeout as it tries to respond.
Here is my docker yaml setup. I assume MassTransit pulls its settings to connect from appsettings.json.
version: '3.4'
services:
hostedservice:
environment:
- ASPNETCORE_ENVIRONMENT=development
ports:
- "80"
rabbitmq3:
hostname: "rabbitmq"
image: rabbitmq:3-management
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
- RABBITMQ_DEFAULT_VHOST=/
ports:
# AMQP protocol port
- '5672:5672'
# HTTP management UI
- '15672:15672'
I'd suggest using the MassTransit Docker template to get a working setup. Or you can look at the source code and see how when running in a container, the template using rabbitmq as the host name to connect.
You can download the template using NuGet.
Thanks Chris that moved me to the container template usage that cleared up the connection issue!

Not able to connect ActiveMQ docker container from another docker container

version: '3.9'
services:
activemq:
image: rmohr/activemq:5.15.9-alpine
restart: always
ports:
- 61616:61616
- 8161:8161
- 5672:5672
container_name: activemq
app-service:
image: app-service:v1
restart: always
ports:
- 8080:8080
container_name: app-service
links:
- activemq
depends_on:
- activemq
In my app service I've configured the ActiveMQ broker URL using Spring Boot spring.activemq.broker-url=tcp://activemq:61616 and also username and password.
When I am trying to run docker-compose up the app service showing below error
DefaultMessageListenerContainer : Could not refresh JMS Connection for
destination 'queueName' - retrying using FixedBackOff{interval=5000,
currentAttempts=5, maxAttempts=unlimited}. Cause: Java.lang.NullPointerException.
I can access the ActiveMQ web console on browser (e.g. using http://localhost:8161).
Without docker container the same code is working fine in localhost.
I also had this exact problem and what helped me is adding spring.activemq.broker-url=tcp://activemq:61616 to docker-compose for app environment tag. For me it's like that:
app:
build:
context: .
container_name: app
ports:
- 8080:8080
environment:
- spring.activemq.broker-url=tcp://activemq:61616
depends_on:
- activemq
I think containerized spring app doesn't see broker-url from app properties for whatever reason
Yes, The big reason is your app run before activemq service.
You can try docker-compose up and see the console log in terminal.
Fixed:
It is not a good idea yet,but you can go to docker app and click on restart with you app container's name and then everything will work.

Docker-compose links container but Application throws "no route found"

I have a web application with database and rabbitMQ services. I am using docker-compose to build and run images.
rabbitmq:
image : rabbitmq:3-management
container_name: rabbitmq
hostname: rabbitmq
ports:
- "15672:15672"
expose:
- "5672"
- "4369"
- "25672"
coredb:
container_name: coredb
build: ./mongodb/
core:
container_name: core
build: ./core/
ports:
- "80:8080"
- "5683/udp:5683/udp"
- "5684/udp:5684/udp"
links:
- rabbitmq
- coredb
After running
docker-compose up
All the services get started properly. I can ping rabbitmq and codedb from core's shell. In the SpringBoot application code, I am using
CachingConnectionFactory(hostname)
to connect to rabbitMQ. The hostname i am giving is "rabbitmq". In the logs during event publishing, the error I see is "No route found". Core service can connect to database properly but cannot connect to rabbitMQ.
You can use docker inspect <container name> to inspect the config of the "core" service to make sure the link was setup. You can also check the hostname using docker exec -ti <container name> cat /etc/hosts (which I think you did already).
If it looks like it's properly linked up, the issue is probably that the core service is trying to connect to it before the rabbitmq service has actually started.
You can have the "core" service retry a few times (with a short delay) to try and setup the conenction.

Resources