Jak utworzyć JAR z aplikacją łączącą się z bazą danych?

Jak utworzyć JAR z aplikacją łączącą się z bazą danych?

Wątek przeniesiony 2024-11-24 11:09 z Dev/ops przez Riddle.

MZ
  • Rejestracja:prawie 3 lata
  • Ostatnio:około 6 godzin
  • Postów:19
1

Cześć. Mam uruchomiony kontener z Postgresem który zaciągnąłem takim yml-em:

Kopiuj
db:
  image: postgres
  container_name: db
  restart: always
  ports:
    - "5431:5432"
  environment:
    POSTGRES_USERNAME: postgres
    POSTGRES_PASSWORD: postgres
    POSTGRES_DB: JPABuddy

Następnie chcę spakować do jara spring-bootową aplikację, która ma się łączyć z tą bazką. Inspektem na kontenerze postgresowym sprawdziłem, że baza działa na IP 172.18.0.2. Zatem moje application.properties wyglądają tak:

Kopiuj
spring.application.name=jpa-demo
spring.datasource.url=jdbc:postgresql://172.18.0.2:5431/JPABuddy
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

Nie udaje mi się zrobić mvn package. Wyskakuje, że próba połączenia nie udała się.

edytowany 1x, ostatnio: Riddle
JB
tell me why there's whisky inthe jar ?
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 11 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10076
2

Cześć @MiletZTalesu! 👋 Fajnie że jesteś na forum.

Co do Twojego pytania - widać przecież po grupie IP, że 172.18.0.2 jest prywatny 😊

MiletZTalesu napisał(a):

Inspektem na kontenerze postgresowym sprawdziłem, że baza działa na IP 172.18.0.2.

Owszem, taki IP jest dostępny w środku kontenera. Mógłbyś się na tym adresie połączyć, gdyby Twoja aplikacja spring-boot również była w tym kontenerze. Ale poza kontenerem, ten sam adres IP 172.18.0.2 odnosi się do prywatnej puli adresów hosta (czyli Twojego systemu operacyjnego), nie do bazy w kontenerze. Kontener działa w innej sieci - w niej adresy są inne.

Pytanie się pojawia - to w takim razie jak się połączyć z czymś w kontenerze? 🤔 Korzystająć z dockera można wybrać różne rodzaje sieci. Jeśli nic nie zmieniałeś, to domyślnym rodzajem będzie bridge. To znaczy, że wszystkie porty które przekierujesz z kontenera do hosta (w Twoim wypadku 5431:5432) będą dostępne z hosta po prostu na adresie lokalnym, 127.0.0.1 lub localhost 😊

Jeśli nic innego nie mieszałeś w ustawieniach dockera, to Twój kontener db będzie dostępny z hosta pod jdbc:postgresql://localhost:5431.

edytowany 6x, ostatnio: Riddle
MZ
  • Rejestracja:prawie 3 lata
  • Ostatnio:około 6 godzin
  • Postów:19
0

Racja. W gruncie rzeczy mam inny problem, ale wydawało mi się, ze wydzieliłem źródło. Chcę zrobić coś takiego: w jednym kontenerze stawiam Postgresa,a w drugim puszczam apkę springbootową, która ma się z tym postgresem łączyć. Mam takie pliki:

Dockerfile

Kopiuj
FROM openjdk:23-jdk

COPY ./target/jpa-demo-1.jar jpa-demo-1.jar

ENTRYPOINT ["java","-jar","jpa-demo-1.jar"]

Compose.yml

Kopiuj
version: '3.8'

services:

  db:
    image: postgres
    container_name: db
    restart: always
    ports:
      - "5431:5432"
    environment:
      POSTGRES_USERNAME: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: JPABuddy

  my_app:
    image: myapp
    build:
      context: .
    ports:
      - "8081:8080"
    depends_on:
      - db

Application.properties

Kopiuj
spring.application.name=jpa-demo
spring.datasource.url=jdbc:postgresql://localhost:5431/JPABuddy
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

Stawiam wszystko tym jednym yamlem. I po komendzie docker ps -a widzę, że mój webservice ma status exited(1). A spodziewałbym się, że webservice sam się nie zabije.Nie wiem jak mogę to głębiej zbadać, ale jako, że apka jest trywialna to zakładam, że występuje zgrzyt na płaszczyźnie apka - bazka.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 11 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10076
0

No to trzeba było tak od razu - z Twojego pierwszego posta wynikało że apka springowa ma stać na hoście. Nie rozumiem czemu nie wkleiłeś od razu wszystkiego do wątku 😕

Jeśli obie aplikacje (baza i Twoja) są w kontenerach oraz korzystasz z domyślnej sieci w dockerze (czyli bridge), to kontenery mogą ze sobą rozmawiać używając swoich nazw kontenerów jako hostname'ów. Czyli jeśli Twój kontener nazywa się db, to powinieneś móc się połączyć z innego kontenera z nim przez jdbc:postgresql://db:5431/JPABuddy.

edytowany 2x, ostatnio: Riddle
MZ
  • Rejestracja:prawie 3 lata
  • Ostatnio:około 6 godzin
  • Postów:19
0

Coś takiego próbowałem. Ale jeśli wkładam jdbc:postgresql://db:5431/JPABuddy do Application.properties to z poziomu Intelij-a nie daje się zbudować jarki mavenem. Z błędem "Próba nawiązania połączenia nie powiodła się."

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 11 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10076
0
MiletZTalesu napisał(a):

Coś takiego próbowałem. Ale jeśli wkładam jdbc:postgresql://db:5431/JPABuddy do Application.properties to z poziomu Intelij-a nie daje się zbudować jarki mavenem. Z błędem "Próba nawiązania połączenia nie powiodła się."

Wklej cały swój kod i pokaż wszystko co robisz.

MZ
  • Rejestracja:prawie 3 lata
  • Ostatnio:około 6 godzin
  • Postów:19
0

Apka jest zwykła. Kontroller, serwis, spring data. Nie chcę zaśmiecać kodem, taki standard totalny. Wypełniam przy stawianiu bazę z uzyciem Springowego CommandLineRunner-a jakimiś danymi przykładowymi w ten sposób:

Kopiuj
@Override
	public void run(String... args) throws Exception {
		Author author = new Author("Mickiewicz");
		authorRepository.save(author);
		Book book = new Book("abecadlo",author);
		bookRepository.save(book);
	}

Jeśli puszczam to na bazie lokalnej to normalnie śmiga. Odpalam sobie yml-em postgresowy kontener.

Gdy daję w Application.properties zapis spring.datasource.url=jdbc:postgresql://localhost:5431/JPABuddy i buduję jarkę w Intelij-u, a potem odpalam aplikację to normalnie ten mój webserwis operuje na bazce w kontenerze prawidłowo.

Problem pojawia się gdy chcę webserwis skonteneryzować także. Tam powyżej wrzuciłem całego ymla i dockerfila, jak to robię. Bo jeśli dobrze rozumiem to zapis(w propertisach) jdbc:postgresql://localhost:5431/JPABuddy mam zamienić na jdbc:postgresql://db:5431/JPABuddy. Ale jeśli go zamieniam to nie mogę tego spakować do jara, z błędem "Próba nawiązania połączenia nie powiodła się". Jeśli natomiast nie zamieniam i buduję z localhostem, to z kolei ten mój webservice działa jakieś 20 sekund i pada.
docker.jpg

opiszon
  • Rejestracja:prawie 3 lata
  • Ostatnio:około 7 godzin
  • Postów:780
0

Kiedy dokładnie ta próba połączenia się nie udaje? (Samo mvn package to za mało info)
Może np w testach integracyjnych i po prostu skonteneryzowana apka nie może się dobić do bazy?
Używasz jakiegoś pluginu mavenowego do budowania obrazu dockerowego?

edytowany 1x, ostatnio: opiszon
ZI
  • Rejestracja:ponad 8 lat
  • Ostatnio:7 dni
  • Postów:230
0

Z tego co rozumiem to podczas budowy laczysz sie z baza z hosta (i wtedy localhost dziala) a potem proboujesz odpalic to w dockerze i juz nie lokalhost a db powinnno byc.

Rozwizanie to przygotowanie sobie dwoch plikow z propertisami i odpalanie springboota w odpowiednim profilu (build/prod)

Lokalnie ustawiasz zeby aplikacja wstawala z profilem build a w dockerze ustawiasz aplikacji profil prod

MZ
  • Rejestracja:prawie 3 lata
  • Ostatnio:około 6 godzin
  • Postów:19
0

Spróbowałem z tymi profilami. Dorobiłem osobnego propertisa dla db. W Dockerfilu mam ENTRYPOINT ["java","-Dspring.profiles.active=prod","-jar","jpa-demo-1.jar"].
W zależności z którym profilem odpalam to dostaję w kontenerze z webservicem albo:

Kopiuj
Connection to db:5431 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

albo

Kopiuj
Connection to localhost:5431 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

Pluginu mavenowego nie używam. Skonteneryzowana apka nie chce się dobić do skonteneryzowanej bazy, ale jeśli tej apki nie konteneryzuję to do skonteneryzowanej bazy się dobija bez problemu.

edytowany 1x, ostatnio: Riddle
KE
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 11 godzin
  • Postów:681
2

Chyba powinno być db:5432 zamiast db:5431. Wewnątrz sieci dockerowej porty są takie, jakie kontener wystawia. Poza siecią dockerową, porty są mapowane. Ale nie jestem pewien, sprawdź.

MA
  • Rejestracja:ponad rok
  • Ostatnio:dzień
  • Postów:50
1

Można też zadeklarować health check na db, który oznajmi, że kontener jest 'zdrowy' po zakończeniu inicjalizacji, a apka dopiero po poprawnej inicjalizacji bazy danych i zwróceniu przez nią odpowiedniego health checka zacznie się podnosić.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.