Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker Compose + Spring Boot + Postgres connection

I have a Java Spring Boot app which works with a Postgres database. I want to use Docker for both of them. I initially put just the Postgres in Docker, and I had a docker-compose.yml file defined like this:

version: '2'
services:
    db:
        container_name: sample_db
        image: postgres:9.5
        volumes:
            - sample_db:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=sample
            - POSTGRES_USER=sample
            - POSTGRES_DB=sample
            - PGDATA=/var/lib/postgresql/data/pgdata
        ports:
            - 5432:5432

volumes:
    sample_db: {}

Then, when I issued the commands sudo dockerd and sudo docker-compose -f docker-compose.yml up, it was starting the database. I could connect using pgAdmin for example, by using localhost as server and port 5432. Then, in my Spring Boot app, inside the application.properties file I defined the following properties.

spring.datasource.url=jdbc:postgresql://localhost:5432/sample
spring.datasource.username=sample
spring.datasource.password=sample
spring.jpa.generate-ddl=true

At this point I could run my Spring Boot app locally through Spring Suite, and it all was working fine. Then, I wanted to also add my Spring Boot app as Docker image. I first of all created a Dockerfile in my project directory, which looks like this:

FROM java:8
EXPOSE 8080
ADD /target/manager.jar manager.jar
ENTRYPOINT ["java","-jar","manager.jar"]

Then, I entered to the directory of the project issued mvn clean followed by mvn install. Next, issued docker build -f Dockerfile -t manager . followed by docker tag 9c6b1e3f1d5e myuser/manager:latest (the id is correct). Finally, I edited my existing docker-compose.yml file to look like this:

version: '2'
services:
    web:
      image: myuser/manager:latest
      ports: 
          - 8080:8080
      depends_on:
          - db
    db:
        container_name: sample_db
        image: postgres:9.5
        volumes:
            - sample_db:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=sample
            - POSTGRES_USER=sample
            - POSTGRES_DB=sample
            - PGDATA=/var/lib/postgresql/data/pgdata
        ports:
            - 5432:5432

volumes:
    sample_db: {}

But, now if I issue sudo docker-compose -f docker-compose.yml up command, the database again starts correctly, but I get errors and exit code 1 for the web app part. The problem is the connection string. I believe I have to change it to something else, but I don't know what it should be. I get the following error messages:

web_1  | 2017-06-27 22:11:54.418 ERROR 1 --- [           main] o.a.tomcat.jdbc.pool.ConnectionPool      : Unable to create initial connections of pool.
web_1  | 
web_1  | 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

Any ideas?

like image 273
typos Avatar asked Jun 27 '17 22:06

typos


2 Answers

Each container has its own network interface with its own localhost. So change how Java points to Postgres:

spring.datasource.url=jdbc:postgresql://localhost:5432/sample

To:

spring.datasource.url=jdbc:postgresql://db:5432/sample

db will resolve to the proper Postgres IP.


Bonus. With docker-compose you don't need to build your image by hand. So change:

web:
  image: myuser/manager:latest

To:

web:
  build: .
like image 102
Robert Avatar answered Nov 16 '22 13:11

Robert


I had the same problem and I lost some time to understand and solve this problem:

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 show all the properties so that everyone understands.
application.properties:

spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect
spring.jpa.hibernate.ddl-auto=update

docker-compose.yml:

  version: "3"
  services:
    springapp:
      build: .
      container_name: springapp
      environment:
        SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/testdb
      ports:
        - 8000:8080
      restart: always
      depends_on:
        - db
    db:
      image: postgres
      container_name: db
      environment:
        - POSTGRES_USER=postgres
        - POSTGRES_PASSWORD=postgres
        - POSTGRES_DB=testdb
        - PGDATA=/var/lib/postgresql/data/pgdata
      ports:
        - 5000:5432
      volumes:
        - pgdata:/var/lib/postgresql/data
      restart: always
  volumes:
    pgdata:

For start spring application with local database we use url localhost.
For connect to container with database we need change 'localhost' on your database service, in my case 'localhost' to 'db'.

Solution: add SPRING_DATASOURCE_URL environment in docker-compose.yml wich rewrite spring.datasource.url value for connect:

  environment:
    SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/testdb

I hope this helps someone save his time.

like image 26
Alexander Yushko Avatar answered Nov 16 '22 11:11

Alexander Yushko