I am attempting to build a "service" consisting of a Spring Boot application and PostgreSQL database. I have been able to access the database (running in a container) from the Spring Boot app while the Spring Boot application was running on my local machine. Now, when I attempt to move the Spring Boot application to a container, I am received the following error:
inventory_1 | 2018-01-20 18:43:06.108 ERROR 1 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection] with root cause
inventory_1 |
inventory_1 | java.net.ConnectException: Connection refused (Connection refused)
However, I am able to connect to DB from my local machine:
psql -h localhost -p 5000 -U kelly_psql -d leisurely_diversion
My application.properties file:
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=false
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.url=jdbc:postgresql://localhost:5432/leisurely_diversion
spring.datasource.username=kelly_psql
spring.datasource.password=pass
spring.datasource.driver-class-name=org.postgresql.Driver
My docker-compose file:
# Use postgres/example user/password credentials
version: '3.2'
services:
db:
image: postgres
ports:
- 5000:5432
environment:
POSTGRES_PASSWORD: example
volumes:
- type: volume
source: psql_data
target: /var/lib/postgresql/data
networks:
- app
restart: always
inventory:
image: kellymarchewa/inventory_api
depends_on:
- db
ports:
- 8080:8080
networks:
- app
restart: always
volumes:
psql_data:
networks:
app:
My Dockerfile (from the Spring website)
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
I suspect the issue lies in a misunderstanding (on my part) of Docker or containers, but I am not sure. Any advice would be appreciated.
You are pointing your application towards localhost, but this is not shared between containers.
To access another container you have to refer to its hostname.
In your case, I understand that you want the inventory service to access the db service. So you should use the following datasource url:
spring.datasource.url=jdbc:postgresql://db:5432/leisurely_diversion
See this simple tutorial about connecting to a container from another container with docker compose: https://docs.docker.com/compose/gettingstarted/
Like in my case if you are using Docker Toolbox for windows 8.1 then you cannot use "localhost",
Instead you have to use docker machine ip;
host> docker-machine ip default
192.168.99.100
After that your url will look like;
spring.datasource.url=jdbc:postgresql://192.168.99.100:5432/bankdb
This will successfully connect to docker Postgres DB.
Cheers!!
Elaborating a little upon the answer given by ESala:
I agree, it is a networking issue and the given solution works fine, but you can also use localhost (e.g. if you really really want to), by switching to network host mode when running your containers (cf here). Like done here for nginx.
I'd say you won't want this most of the time, since it messes with the sandbox you gain. But the option exists.
Related
I have a problem here that I really cannot understand. I already saw few topics here with the same problem and those topics was successfully solved. I basically did the same thing and cannot understand what I'm doing wrong.
I have a Spring application container that tries to connect to a Mongo container through the following Docker Composer:
version: '3'
services:
app:
build: .
ports:
- "8080:8080"
links:
- db
db:
image: mongo
volumes:
- ./database:/data
ports:
- "27017:27017"
In my application.properties:
spring.data.mongodb.uri=mongodb://db:27017/app
Finally, my Dockerfile:
FROM eclipse-temurin:11-jre-alpine
WORKDIR /home/java
RUN mkdir /home/java/bar
COPY ./build/libs/foo.jar /home/java/bar/foo.jar
CMD ["java","-jar", "/home/java/bar/foo.jar"]
When I run docker compose up --build I got:
2022-11-17 12:08:53.452 INFO 1 --- [null'}-db:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server db:27017
Caused by: java.net.UnknownHostException: db
Running the docker compose ps I can see the mongo container running well, and I am able to connect to it through Mongo Compass and with this same Spring Application but outside of container. The difference running outside of container is the host from spring.data.mongodb.uri=mongodb://db:27017/app to spring.data.mongodb.uri=mongodb://localhost:27017/app.
Also, I already tried to change the host for localhost inside of the spring container and didnt work.
You need to specify MongoDB host, port and database as different parameters as mentioned here.
spring.data.mongodb.host=db
spring.data.mongodb.port=27017
spring.data.mongodb.authentication-database=admin
As per the official docker-compose documentation the above docker-compose file should worked since both db and app are in the same network (You can check if they are in different networks just in case)
If the networking is not working, as a workaround, instead of using localhost inside the spring container, use the server's IP, i.e, mongodb://<server_ip>:27017/app (And make sure there is no firewall blocking it)
I have a spring application with flyway and psql. After
mvn clean install
sudo docker build -t air-travels-api.jar .
docker run -p 8080:8080 air-travels-api.jar
I stuck with an error:
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.
2022-07-09 14:28:09.610 WARN 1 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.internal.exception.FlywaySqlException: Unable to obtain connection from database: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
Here's my docker-compose.yaml:
version: '3'
services:
air-travels-api:
image: air-travels-api
build:
context: .
container_name: air-travels-api
ports:
- "8080:8080"
depends_on:
- flyway
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://air-travels-api-db:5432/air-travels-api
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=postgres
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
flyway:
image: boxfuse/flyway:5-alpine
command: -url=jdbc:postgresql://air-travels-api-db:5432/air-travels-api -schemas=public -user=postgres -password=postgres migrate
volumes:
- ./migration:/flyway/sql
depends_on:
- air-travels-api-db
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=air-travels-api
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- POSTGRES_SCHEMA=public
air-travels-api-db:
image: postgres:12
restart: always
ports:
- "5432:5432"
container_name: air-travels-api-db
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: air-travels-api
Dockerfile:
FROM adoptopenjdk:11-jre-hotspot
EXPOSE 8080
ADD target/air-travels-api-0.0.1-SNAPSHOT.jar air-travels-api.jar
ENTRYPOINT ["java", "-jar", "/air-travels-api.jar"]
Applicaton.yaml
spring:
datasource:
url: jdbc:postgresql://air-travels-api-db:5432/air-travels-api
username: postgres
password: postgres
I found a similar question on stackoverflow, they suggested making sure postgres is running on the local machine. But I have it running inside a container (air-travels-api-db).
There are 2 issues that I see:
In the Application.yaml your url should be
jdbc:postgresql://air-travels-api-db:5432/air-travels-api
since your database service has the hostname air-travels-api-db and not localhost.
In your flyway service in docker-compose.yaml, the url is also incorrect. It should point to air-travels-api-db instead of postgres.
command: -url=jdbc:postgresql://api-travels-api-db:5432/air-travels-api -schemas=public -user=postgres -password=postgres migrate
You do set the environment variable, but it is possible the command-line argument will override that.
One suggestion: Database containers are known to have a slow startup, therefore, it is a good idea to either add a health-check to your database service, or make sure to implement retry logic in your application. Otherwise, you will see race condition issues where the application runs before the database is available and it crashes. This is very common.
I have a few microservices running under Docker. They are Zuul, Eureka, and a configuration server. These are working but when I start my authorization-service, it says I cannot connect to PostgreSQL.
version: '3'
services:
eureka-discovery:
...
zuul-gateway:
...
config:
...
postgres:
image: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: root
POSTGRES_DB: spring_microservices
ports:
- 5432:5432
authorization-service:
image: authorization-service:0.0.1
environment:
- eureka.client.serviceUrl.defaultZone=http://eureka-discovery:8761/eureka
- spring.cloud.config.uri=http://zuul-gateway:8765/config-service
- spring.datasource.url=jdbc:postgresql://postgres:5432/spring_microservices
depends_on:
- eureka-discovery
- zuul-gateway
- config
- postgres
ports:
- 1001:1001
What's confusing is that I am specifying postgres instead of localhost to make the connection, but the error continues to say "localhost". You see I override other properties the same way I do with spring.datasource.url and they work but this one.
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.
I attempted a few variations I could find around, such as using a different service name, using SPRING_DATASOURCE_URL, using the connection string as postgresql://[user]:[pass]#[service]/[database], I tried moving this line to the config-service instead since the database connection is indeed in the Spring Cloud Config Server microservice, but all to no avail. What's missing? It seems to be correct comparing to all the solutions I found.
I made Spring Config Server see my repository for the configurations. Thinking better, if it's reading from the repository it's evident that changing it on the fly locally won't work, so I updated the connection string of the configuration file for authorization-service then pushed, and it worked. I wonder if this is a good practice or better to make Config Server see local files and change it on the fly?
Hi i hope you are okay !
above your authorization-service add a link like this:
links:
- "postgres"
Greetings
I want to create web services with Spring boot, add it to docker image, connect to cloud sql and then run on Compute Engine.
I am using docker compose to combine the image for project and cloud sql proxy image. However, no matter what jdbc URL I give it fails to connect. Right now, I am trying all of this locally
I have tried following URLs:
1. spring.datasource.url=jdbc:mysql:///cloudsql/myinstancename/${MYSQL_DATABASE}
2. spring.datasource.url=jdbc:mysql://cloudsql/myinstancename/${MYSQL_DATABASE}
3. spring.datasource.url=jdbc:mysql://127.0.0.1:3306/${MYSQL_DATABASE}
docker-compose.yml
version: '3'
services:
app:
image: appname
volumes:
- cloudsql:/cloudsql
depends_on:
- sql_proxy
ports:
- 8080:8080
# SQL proxy is built correctly, says
# Listening on /cloudsql/myinstancename for myinstancename
# sql_proxy_1 | Ready for new connections
sql_proxy:
environment:
- MYSQL_ROOT_PASSWORD=password!#
- MYSQL_DATABASE=appname
- MYSQL_USER=root
image: gcr.io/cloudsql-docker/gce-proxy:1.12
command:
/cloud_sql_proxy
-dir=/cloudsql
-instances=myinstancename # (I have added this correctly)
-credential_file=/root/keys/keyfile.json
volumes:
- E:\mykey.json:/root/keys/keyfile.json:ro
- cloudsql:/cloudsql
ports:
- 3306:3306
volumes:
# This empty property initializes a named volume.
cloudsql:
application.properties:
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql:///cloudsql/myinstancename/${MYSQL_DATABASE}
spring.datasource.username=${MYSQL_USER}
spring.datasource.password=${MYSQL_ROOT_PASSWORD}
spring.security.enabled=false
security.ignored=/**
Currently, you are using the Cloud SQL proxy in a sidecar pattern that is mounting a unix socket in /cloudsql/<INSTANCE_CONNECTION_NAME> that can be used to connect to your Cloud SQL instance. Unfortunately, most Java JDBC drivers don't support unix sockets. You can switch the Cloud SQL Proxy to provide a tcp socket instead with something like the following: "-instances=<INSTANCE_CONNECTION_NAME>=tcp:3306".
Alternatively, you can use the Cloud SQL JDBC Socket Factory. This is a Java library that allows you to create authenticated connections to a Cloud SQL instance, but doesn't require using the proxy.
I am developing a web application by using the Spring Boot, Spring Cloud Config and Docker. There are 3 projects. One is springboot web, Spring Cloud Config Server and MySql Database. I have use the Spring Boot Web with Themeleaf. It's basically perform a CRUD operation. In the development phase it's working fine. But when I deploy it in the Docker
Spring-Boot webapp container(springboot-thymeleaf-web-crud) is giving me the following error--
APPLICATION FAILED TO START
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
I have created 3 container on Docker Compose file.
version: '3'
services:
springboot-thymeleaf-web-crud:
image: numery/springboot-thymeleaf-web-crud:latest
networks:
- employee-network
ports:
- 8080:8080
depends_on:
- employee-database
- spring-cloud-config-server-employee
spring-cloud-config-server-employee:
image: numery/spring-cloud-config-server-employee:latest
networks:
- employee-network
ports:
- 8888:8888
employee-database:
image: mysql:5
networks:
- employee-network
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=employee_directory
volumes:
- /home/numery/Docker-Database/employee_directory:/var/lib/mysql
networks:
employee-network:
SpringBoot Web Application.properties is given below
spring.application.name=employee-service-mysql
server.port=8080
spring.cloud.config.uri=http://spring-cloud-config-server-
employee:8888
spring.profiles.active=dev
SpringBoot Config Server is providing the following properties--
spring.datasource.url: jdbc:mysql://employee-
database:3306/employee_directory?
useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username: root
spring.datasource.password: rootpassword
spring.datasource.validationQuery: SELECT 1
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.tomcat.max-wait: 20000
spring.tomcat.max-active: 50
spring.tomcat.max-idle: 20
spring.tomcat.min-idle: 15
spring.jpa.properties.hibernate.dialect:
org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql: true
spring.jpa.format-sql: true
spring.jpa.database: MYSQL
spring.jpa.hibernate.ddl-auto: create
Out of these 3 containers Mysql and Spring Cloud Config container is working fine. But for the Spring Boot Webapp(springboot-thymeleaf-web-crud) is exiting by giving the error above.
Note: I use the same datasouce(Spring Data JPA) configuration on some other SpringBoot Rest API. Which are working fine. But this is the first time I am using SpringBoot Web. Do I need to explicitly define any configuration on the data-source.
Please help!!
The datasource URL, that is spring.datasource.url: jdbc:mysql://employee- may be wrong.
OR Should add your datasource url to your Application.properties file
The url should be in the format jdbc:oracle:thin:#hostname:portNumber/schemaName
For further details and clarification, Not using the hostname and port in jdbc url
I perform the following task to solve the problem--
1) We should have up and running the mysql
container.
2) Inspect mysql container which ip running--
docker inspect mysqlcontainer | grep IP
3) Add the IP of that mysql container to my
springboot web app--
"spring.datasource.url:
jdbc:mysql://172.20.0.2:3306/employee_directory?
useSSL=false&serverTimezone
=UTC&useLegacyDatetimeCode=false"
4) run mvn clean, mvn install and build the
SpringBoot Web image.
5) If we down the container we need to perform the
same task again. Because each time Mysql
container obtain the different ip.