Search code examples
springdockerhibernatedocker-compose

Using Docker for I receive - java.net.ConnectException: Connection refused - applications running on 8088,8089 and DB running on 5432


I use Docker-Compose for DB container and it is running on 5432 (default port). and also I created two services on Spring boot which are running on 8088 and second on 8089 ports. The DB and Services are running on two different containers.

the Docker-Compose file for DB :

version: "3.9"
services:
    postgres:
        container_name: postgres_container
        image: postgres:16.3-alpine3.20
        command:
          - "postgres"
          - "-c"
          - "max_connections=50"
          - "-c"
          - "shared_buffers=1GB"
          - "-c"
          - "effective_cache_size=4GB"
          - "-c"
          - "work_mem=16MB"
          - "-c"
          - "maintenance_work_mem=512MB"
          - "-c"
          - "random_page_cost=1.1"
          - "-c"
          - "temp_file_limit=10GB"
          - "-c"
          - "log_min_duration_statement=200ms"
          - "-c"
          - "idle_in_transaction_session_timeout=10s"
          - "-c"
          - "lock_timeout=1s"
          - "-c"
          - "statement_timeout=60s"
          - "-c"
          - "shared_preload_libraries=pg_stat_statements"
          - "-c"
          - "pg_stat_statements.max=10000"
          - "-c"
          - "pg_stat_statements.track=all"
          
        environment:
            POSTGRES_DB: "my_test_db"
            POSTGRES_USER: "username"
            POSTGRES_PASSWORD: "password"
            PGDATA: "/var/lib/postgresql/data/pgdata"
        volumes:
          - ./2. Init Database:/docker-entrypoint-initdb.d
          - my_test_db-data:/var/lib/postgresql/data
          - ./logs:/logs
        ports:
          - "5432:5432"
        healthcheck:
            test: ["CMD-SHELL","pg_isready -U username-d my_test_db"]
            interval: 10s
            timeout: 5s
            retries: 5
            start_period: 10s
        restart: unless-stopped
        deploy: 
            resources:
                limits:
                    cpus: '1'
                    memory: 4G
        networks:
          - postgres
          
volumes:
    my_test_db-data:
    
networks:
    postgres:
        driver: bridge

and Docker-Compose for Spring services:

version: '3'
services:
    user-service:
        container_name: user-service
        image: user-service
        build:
          context: usersMicro
          dockerfile: Dockerfile
        ports:
          - "8089:8081"
        environment:
            SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/my_test_db
            SPRING_DATASOURCE_USERNAME: username
            SPRING_DATASOURCE_PASSWORD: password
    order-service:
        container_name: order-service
        image: order-service
        build:
          context: orderMicro
          dockerfile: Dockerfile
        ports:
          - "8088:8081"
        environment:
            SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/my_test_db
            SPRING_DATASOURCE_USERNAME: username
            SPRING_DATASOURCE_PASSWORD: password  
networks:
    to_postgres:
      driver: postgres
      external: true

I am able to connect to DB with command line or from IDE, but when I try to run the services on docker, I receive the message - java.net.ConnectException: Connection refused

user-service   | Caused by: java.net.ConnectException: Connection refused
user-service   |        at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]
user-service   |        at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na]
user-service   |        at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) ~[na:na]
user-service   |        at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597) ~[na:na]
user-service   |        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na]
user-service   |        at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na]
user-service   |        at org.postgresql.core.PGStream.createSocket(PGStream.java:243) ~[postgresql-42.7.3.jar!/:42.7.3]
user-service   |        at org.postgresql.core.PGStream.<init>(PGStream.java:98) ~[postgresql-42.7.3.jar!/:42.7.3]
user-service   |        at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:136) ~[postgresql-42.7.3.jar!/:42.7.3]
user-service   |        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:262) ~[postgresql-42.7.3.jar!/:42.7.3]
user-service   |        ... 63 common frames omitted

Solution

  • Each docker container has it's own IP, and also it's own loopback network, so localhost in the spring container is not the localhost of the postgres database or the localhost of the host machine.

    If they are on the same virtual network, the docker daemon has it's own DNS service that assigns the service name to the IP of the container, so you need to link them like this:

    SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/my_test_db
    

    Also, if you put the services in different docker-compose files, you need to configure them to use the same network. I think you need to give them the same name, and define it as external in one of the docker-compose files.

    You also need to specifically add the network to each service, it's not enough to define the network at the end of the docker-compose file:

    services:
      postgres:
        networks:
          - postgres
    networks:
      postgres:
        name: shared-network
        driver: bridge
    
    services:
      user-service:
        networks:
          - postgres
      order-service:
        networks:
          - postgres
    networks:
      postgres:
        name: shared-network
        external: true
    

    See also: Communication between multiple docker-compose projects