7

I am building my first Springboot 2.0 application. I am trying to put my Springboot application into one docker container and my PostgresDB into another container.

My Dockerfile

    FROM frolvlad/alpine-oraclejdk8:slim
    VOLUME /tmp
    ADD springboot-api-demo-0.1*.jar app.jar
    RUN sh -c 'touch /app.jar'
    EXPOSE 9443
    ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/urandom -jar /app.jar" ]

My docker-compose.yml file

version: "2.1"

services:
  springboot-api-demo:
    image: "fw/springboot-api-demo"
    mem_limit: 1024m
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=local
      - AWS_REGION=local
      - ENVIRONMENT=local
      - AUTH_ENABLED=false
  postgres:
    container_name: pgdb
    image: postgres:9.6-alpine
    environment:
    - 'POSTGRES_ROOT_PASSWORD=postgres'
    - 'POSTGRES_USER=postgres'
    - 'POSTGRES_PASSWORD=postgres'
    ports:
    - "54321:5432"

I am using Springboot JPA Data 2.0 with below config data in my application.properties

spring.datasource.url= jdbc:postgresql://localhost:54321/java_learning
spring.datasource.username=postgres
spring.datasource.password=postgres

I can test that Both of the Images are up. Also from docker log and docker events, I see that postgres Container is running fine, even I can access it and also created a DB too. But springboot container started but i died because it could not connect to postgress and throwing error below.

Unable to obtain connection from database: The connection attempt failed

Note that my host machine already has Postgres on port 5432 thats why I did a port mapping ofr 54321:5432 on my postgres container. Here is Proof :) -

➜  springboot-api-demo git:(master) ✗ lsof -i:54321              
COMMAND     PID             USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
com.docke 44345 shailendra.singh   18u  IPv4 0xf62897fbdd69e31d      0t0  TCP *:54321 (LISTEN)
com.docke 44345 shailendra.singh   21u  IPv6 0xf62897fbdd119975      0t0  TCP localhost:54321 (LISTEN)

➜  springboot-api-demo git:(master) ✗ lsof -i:5432 
COMMAND  PID             USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
postgres 715 shailendra.singh    5u  IPv6 0xf62897fbb43e03b5      0t0  TCP localhost:postgresql (LISTEN)
postgres 715 shailendra.singh    6u  IPv4 0xf62897fbbaeea9bd      0t0  TCP localhost:postgresql (LISTEN)

I am not sure what is the problem. But my Springboot application is not able to connect my postgres container which is running fine with proper creadentials.

4 Answers 4

7

Try with :

spring.datasource.url= jdbc:postgresql://pgdb:5432/java_learning

The postgres database is not running on localhost, it's running in the other container which has an other IP (yet unknown).

Thanksfully, docker-compose automatically create a network shared among all the containers in the docker-compose.yml (unless explicitly said to do not), as a result you can magically use the service name as an hostname.

Also, you have a typo in the port, Postgres use 5432 by default, not 54321

Sign up to request clarification or add additional context in comments.

3 Comments

No It is not working. I tried with host as pgdb. It showing error Message : Connection to pgdb:54321 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
Woops, i missed an other error, the port is actually 5432 not 54321. I've edited my answer
In addition to @AnthonyRaymond's answer, you actually don't need to expose the database port to be able to connect from the springboot-api-demo service, as the services would communicate via internal network anyway. You would need to expose it only if you will be connecting to the db port remotely from another machine.
4

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.

you should use the following datasource url:

spring.datasource.url=jdbc:postgresql://pgdb:5432/java_learning

See this simple tutorial about connecting to a container from another container with docker compose: https://docs.docker.com/compose/gettingstarted/

2 Comments

No for that also It is not working. I tried with host as pgdb. It showing error Message : Connection to pgdb:54321 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections. –
try with 5432 instead of 54321
2

You're missing networking configuration in your docker-compose.yml specification. By using "networks" you can effectively communicate between containers by their service name (using dns, the service name as the hostname).

Here is an updated docker-compose.yml:

version: "2.1"

services:
  springboot-api-demo:
    image: "fw/springboot-api-demo"
    mem_limit: 1024m
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=local
      - AWS_REGION=local
      - ENVIRONMENT=local
      - AUTH_ENABLED=false
    networks:
      - mynet

  postgres:
    container_name: pgdb
    image: postgres:9.6-alpine
    environment:
    - 'POSTGRES_ROOT_PASSWORD=postgres'
    - 'POSTGRES_USER=postgres'
    - 'POSTGRES_PASSWORD=postgres'
    ports:
    - "54321:5432"
    networks:
    - mynet

networks:
  mynet:
    driver: bridge

Your database url should look like spring.datasource.url=jdbc:postgresql://postgres:5432/java_learning (notice the hostname, postgres, is equal to that of the service name.

1 Comment

Also, I would highly advise upgrading docker-compose to >3.x
0

Apart from the above solutions provided JDK 11 java container with the mentioned configuration (connecting postgres via IP, localhost, servicename .. with postgres container exposed to LAN) still doesn't work. Upgrade to JDK latest version (17 currently) works for me - do consider this also when you use JDK 11 and trying java container (docker) communicating with postgres container.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.