wick3d
wick3d

Reputation: 1392

How to connect to docker-compose port from docker and locally?

I am using spring boot 2.5.3 and postgreSQL for backend.

I want this app to run on localhost:5000/api/v1/customers as well as from docker-compose.

application.properties:

server.port=5000
#Database setup
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/customers
spring.datasource.username=postgres
spring.datasource.password=postgres

This works with localhost, with mvn spring-boot:run

But, when I use the following application.properties settings from localhost to db

server.port=5000
#Database setup
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://db:5432/customers
spring.datasource.username=postgres
spring.datasource.password=postgres

Dockerfile

FROM maven:3.8.1-openjdk-11-slim
COPY ./target/customer-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

docker-compose.yml

version: '3.1'
services:
  app:
    container_name: customer-container
    image: customer-image:v1
    build: ./
    ports:
      - "5000:5000"
    depends_on:
      - db
  db:
    image: postgres
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_DB=customers

I cannot connect to localhost:5000/api/v1/customers after mvn spring-boot:run Error:

org.postgresql.util.PSQLException: Connection to db:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:303) ~[postgresql-42.2.23.jar:42.2.23]
        at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) ~[postgresql-42.2.23.jar:42.2.23]
        at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:223) ~[postgresql-42.2.23.jar:42.2.23]
        at org.postgresql.Driver.makeConnection(Driver.java:465) ~[postgresql-42.2.23.jar:42.2.23]
        at org.postgresql.Driver.connect(Driver.java:264) ~[postgresql-42.2.23.jar:42.2.23]

Tried to create a docker image docker build -t customer-image:v1 . , and run docker-compose build docker-compose up there are no error. Logs says it is running on port 5000.

customer-container | 2021-08-29 12:43:42.053  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 5000 (http)
customer-container | 2021-08-29 12:43:42.068  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
customer-container | 2021-08-29 12:43:42.069  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.50]
customer-container | 2021-08-29 12:43:42.189  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
customer-container | 2021-08-29 12:43:42.190  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1876 ms
customer-container | 2021-08-29 12:43:42.487  INFO 1 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
customer-container | 2021-08-29 12:43:42.567  INFO 1 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.32.Final
customer-container | 2021-08-29 12:43:42.702  INFO 1 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
customer-container | 2021-08-29 12:43:42.827  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
customer-container | 2021-08-29 12:43:42.970  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
customer-container | 2021-08-29 12:43:42.995  INFO 1 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
customer-container | 2021-08-29 12:43:43.631  WARN 1 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Warning Code: 0, SQLState: 00000
customer-container | 2021-08-29 12:43:43.631  WARN 1 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : table "customer" does not exist, skipping
customer-container | 2021-08-29 12:43:43.642  INFO 1 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
customer-container | 2021-08-29 12:43:43.656  INFO 1 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
customer-container | 2021-08-29 12:43:44.252  WARN 1 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
customer-container | 2021-08-29 12:43:44.991  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 5000 (http) with context path ''
customer-container | 2021-08-29 12:43:45.290  INFO 1 --- [           main] c.p.customer.CustomerApplication         : Started CustomerApplication in 5.654 seconds (JVM running for 6.531)

This works localhost:5000/api/v1/customers when docker-compose is up.

Is there a way we can have condtional name for host in this line?Is there any other way?

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

Upvotes: 0

Views: 1499

Answers (4)

FlyingTeemo
FlyingTeemo

Reputation: 51

Based on what I see, you are not supposed to use localhost on spring.datasource.url because your docker is within the container itself, you should be using jdbc:postgresql://host.docker.internal:5432/customers instead. For more details, you can view from this link https://docs.docker.com/desktop/windows/networking/#i-cannot-ping-my-containers

Is there a way we can have condtional name for host in this line?Is there any other way? As for this, it would be prefered to set it as an environmetn variable on your docker compose file and connect using dbconn url

Upvotes: 1

David Maze
David Maze

Reputation: 158812

Since the host development environment and the container runtime environment are different, you can use environment variables to differentiate between them. Spring Boot knows how to set Spring properties from environment variables. So I'd recommend:

  • In your application.properties file, set spring.datasource.url to the localhost URL you'd use in development.
  • In your Compose setup, set the SPRING_DATASOURCE_URL environment variable to the name specific to that Compose setup
    version: '3.8'
    services:
       db: { ... }
       app:
         environment:
           - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/customers
         ...
    
  • Do not create a separate Spring profile per environment; you would not want to recompile your jar file if you changed the database name or password, or deployed this in Kubernetes, or used a cloud-hosted database like Amazon RDS, or...

Upvotes: 1

Anirudh Panchangam
Anirudh Panchangam

Reputation: 498

If you are using linux as your operating system on which you are running your docker , you can set this property network_mode: host

on both the containers, this will attach your container's port to your localhost port. You will need to remove the port forwarding config for this to work.

Upvotes: -1

OneCricketeer
OneCricketeer

Reputation: 191701

So, you want to be able to run both locally and from docker?

If that's the case, you need to extract the database connection string to an environment variable that you set at runtime

spring.datasource.url = ${DB_HOST}:${DB_PORT}/
spring.datasource.username = ${DB_USERNAME}
spring.datasource.password = ${DB_PASSWD}

Or you can introduce two different property files that get set from a Spring profile, which you also would set at runtime; Refer SPRING_PROFILES_ACTIVE environment variable

Upvotes: 2

Related Questions