Getting "Exception opening socket" on Mongodb connection from Spring App (docker-compose) - java

Even though I'm giving in the application properties,
spring.data.mongodb.host=api-database4
as the hostname which is the container name and hostname of the MongoDB on the docker-compose file, Spring app still can't connect to the MongoDB instance. I can however connect from MongoDB Compass to localhost:27030 but not to mongodb://api-database4:27030/messagingServiceDb.
My docker-compose file;
version: '3'
services:
messaging-api6:
container_name: 'messaging-api6'
build: ./messaging-api
restart: always
ports:
- 8085:8080
depends_on:
- api-database4
networks:
- shared-net
api-database4:
image: mongo
container_name: api-database4
hostname: api-database4
restart: always
ports:
- 27030:27017
networks:
- shared-net
command: mongod --bind_ip_all
networks:
shared-net:
driver: bridge
and my Docker file for the Spring app is;
FROM openjdk:12-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
and my application.properties are;
#Local MongoDB config
spring.data.mongodb.database=messagingServiceDb
spring.data.mongodb.port=27030
spring.data.mongodb.host=api-database4
Entire code can be seen here.
How can I make my spring app on a docker container create a connection to the MongoDB instance which is on another docker container?
I have tried the solutions on similar questions and replicated them, it still gives the same error.
Edit and Solution:
I solved the issue by commenting out configuration below,
#Local MongoDB config
#spring.data.mongodb.database=messagingServiceDb
spring.data.mongodb.host=api-database4
spring.data.mongodb.port=27030
The remaining question is, why? That was the correct port that I'm trying to connect. Could it be related to the configuration order?

ports directive in docker-compose publishes container ports to the host machine. The containers communicate with each other on exposed ports. You can test whether a container can reach another with netcat.
docker exec -it messaging-api6 bash
> apt-get install netcat
> nc -z -v api-database4 27030
> nc -z -v api-database4 27017

Related

Java container cant connect to MYSQL container with docker-compose

I was given a multy-steps task and im stuck !!
im trying to connect my Java container to my MYSQL container,but im getting 503 ERROR
HTTP ERROR 503
Problem accessing /. Reason:
Service Unavailable
docker-compose file :
version: "3.3"
services:
lavagna:
build: .
ports:
- "8080:8080"
networks:
- back_net
depends_on:
- my_db
environment:
spring.datasource.url: "jdbc:mysql://my-db:3306/lavagna"
my_db:
image: mysql:5.7
ports:
- "3306:3306"
networks:
- back_net
volumes:
- $PWD/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123
MYSQL_USER: eyal
MYSQL_PASSWORD: 123
networks:
back_net:
driver: bridge
I got the JAVA src files,i just used maven localy to build it and use target for the Java Dockerfile
java app dockerfile :
FROM openjdk:8-jre-alpine
EXPOSE 8080
COPY ./target/. .
COPY ./entrypoint.sh .
ENV DB_DIALECT MYSQL
ENV DB_URL jdbc:mysql://localhost:3306/lavagna
ENV DB_USER "root"
ENV DB_PASS "123"
ENV SPRING_PROFILE dev
RUN apk update \
&& apk add ca-certificates \
&& update-ca-certificates && apk add openssl
RUN chmod 774 entrypoint.sh
ENTRYPOINT [ "./entrypoint.sh" ]
I think you need a combination of comments and answers given already. Your containers are on the same network, so it appears to boil down to configuration.
In your docker file update your DB_URL to:
ENV DB_URL jdbc:mysql://my_db:3306/lavagna
If you use localhost your container will loopback to itself, and never hit the network.
In your docker-compose yml file, you have a typo in the url, try updating to:
spring.datasource.url: "jdbc:mysql://my_db:3306/lavagna"
As an aside, using depends_on does not wait for the service to be ready. It simply dictates start order as the documentation states:
There are several things to be aware of when using depends_on:
depends_on does not wait for db and redis to be “ready” before starting web - only until they have been started. If you need to wait for a service to be ready...

Running Spring Boot docker instance with Postgres docker instance

I'm attempting to run a Spring Boot app that connects a Postgres DB using:
docker-compose.yml (for Postgres) :
version: '3'
services:
postgres-db:
container_name: postgres-db
image: postgres:latest
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_password
POSTGRES_DB: shorten-db
To run the Postgres DB:
docker-compose up
.Dockerfile (for the Spring Boot app) :
FROM openjdk:12-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
In order to run the Spring app using Docker I use:
mvn package
docker build -t url-shorten/url-shorten-docker .
docker run -p 8080:8080 url-shorten/url-shorten-docker
But I receive the error when starting when running above docker command:
Caused by: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
In Spring application.properties I connect to the DB using:
spring.datasource.url=jdbc:postgresql://localhost:5432/shorten-db
I think this error is due to the Spring Boot app is running in a different container to DB so it cannot find the DB on localhost. Is there an idiomatic way of connecting the Spring Book docker container to the DB container. Or do I have do access the IP address of my machine and use this address to connect to the Postgres DB running on Docker?
Yes, you can't use localhost in this situation
spring.datasource.url=jdbc:postgresql://postgres-db:5432/shorten-db
In Spring application.properties, try to change DB config to:
spring.datasource.url=jdbc:postgresql://postgres-db:5432/shorten-db
In container networks, You need to use the container name as a host.
You can add both DB and app containers to one Docker network and change PostgreSQL host in datasource URL to postgres-db. Then Spring app will work with your DB.

503 error code for Springboot container connecting to mongo container using docker-compose

I am trying to connect my spring-boot application(REST endpoints) running in a Tomcat container with a mongo container. I am using docker-compose to link both the containers. The application was working perfectly fine. It just stopped working suddenly.
Following is my code:
Dockerfile:
FROM tomcat:9.0.13
WORKDIR /usr/local/tomcat/webapps
#COPY pom.xml .
#RUN ["mvn", "clean", "install"]
COPY /target/TestProfileManager.war .
docker-compose.yml:
version: '3'
services:
app:
container_name: VF-BACKEND
restart: always
build: .
ports:
- "8083:8080" #VF Webservice
depends_on:
- mongo
links:
- mongo
mongo:
container_name: VF-MONGO
image: mongo:4.0.2
ports:
- "27018:27017"
volumes:
- /data/vfdb:/data/db
application.properties
spring.data.mongodb.uri=mongodb://mongo:27018/tsp
If I run the application from the IDE as a standalone application, the endpoints do return the response. Only during container communication, I am getting 503. I could not find any post that answers my question.
Thanks for the help. Since, the code was working before, not pasting the classes. Let me know if I should share them as well.
It should be mongodb://mongo:27017, in service to service communication you do not need to use publish port.
It is important to note the distinction between HOST_PORT and
CONTAINER_PORT. the HOST_PORT is 27018 and the container port is
27017 . Networked service-to-service communication use the
CONTAINER_PORT
compose-networking

Spring Boot + docker-compose + MySQL: Connection refused

I'm trying to set up a Spring Boot application that depends on a MySQL database called teste in docker-compose. After issuing docker-compose up, I'm getting:
Caused by: java.net.ConnectException: Connection refused (Connection refused)
I'm running on Linux Mint, my docker-compose version is 1.23.2, my Docker version is 18.09.0.
application.properties
# JPA PROPS
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.datasource.url=jdbc:mysql://db:3306/teste?useSSL=false&serverTimezone=UTC
spring.datasource.username=rafael
spring.datasource.password=password
spring.database.driverClassName =com.mysql.cj.jdbc.Driver
docker-compose.yml
version: '3.5'
services:
db:
image: mysql:latest
environment:
- MYSQL_ROOT_PASSWORD=rootpass
- MYSQL_DATABASE=teste
- MYSQL_USER=rafael
- MYSQL_PASSWORD=password
ports:
- 3306:3306
web:
image: spring-mysql
depends_on:
- db
links:
- db
ports:
- 8080:8080
environment:
- DATABASE_HOST=db
- DATABASE_USER=rafael
- DATABASE_NAME=teste
- DATABASE_PORT=3306
and the Dockerfile
FROM openjdk:8
ADD target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Docker compose always starts and stops containers in dependency order, or sequential order in the file if not given. But docker-compose does not guarantee that it will wait till the dependency container is running. You can refer here for further details. So the problem here is that your database is not ready when your spring-mysql container tries to access the database. So, the recommended solution is you could use wait-for-it.sh or similar script to wrap your spring-mysql app starting ENTRYPOINT.
As example if you use wait-for-it.sh your ENTRYPOINT in your Dockerfile should change to following after copying above script to your project root:
ENTRYPOINT ["./wait-for-it.sh", "db:3306", "--", "java", "-jar", "app.jar"]
And two other important thing to consider here is:
Do not use links they are deprecated you should use user-defined network instead. All services in docker-compose file will be in single user-defined network if you don't explicitly define any network. So you just have to remove the links from compose file.
You don't need to publish the port for docker container if you only use it inside the user-defined network.
I was facing the same issue and in case you do not want to use any custom scripts, this can easily be resolved using health checks along with depends on. A sample using these is as follows:
services:
mysql-db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=vikas1234
- MYSQL_USER=vikas
ports:
- 3306:3306
restart: always
healthcheck:
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
timeout: 20s
retries: 10
app:
image: shop-keeper
container_name: shop-keeper-app
build:
context: .
dockerfile: Dockerfile
ports:
- 8080:8080
depends_on:
mysql-db:
condition: service_healthy
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/shopkeeper?createDatabaseIfNotExist=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: vikas1234
Your config looks nice, I would just recommend:
Remove links: db. It has no value in user-defined bridge networking
Remove port exposing for db unless you want to connect from outside docker-compose - all ports are exposed automatically inside user-defined bridge network.
I think the problem is that database container takes more time to start than web. depends_on just controls the order, but does not guarantee you database readiness. If possible, set several connection attempts or put socket-wait procedure in your web container.

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?

Categories