Połączenie bazą działającą na hoście z poziomu kontenera docker

0

Cześć,

próbuję z kontenera docker połączyć się z bazą danych która działa na hoście. System linux. Baza postgresql. .net core api na kontenerze.

Znalazłem taki artykuł, i spodobał mi się sposób w jaki autor sugeruje, żeby to zrobić: https://goonan.io/connecting-to-host-database-from-a-docker-container/

Zgodnie z tym co w artykule moj dokcer compose wygląda tak

services:
  app:
    build:
      context: .
    ports:
      - 5000:80
    volumes:
      - /var/run/postgresql/:/var/run/postgresql/

a connection string tak

"connectionString": "Host=/var/run/postgresql;Database=bmw;Username=postgres;Password=password"

Błąd który mam przy próbie połączenia do bazy to

Npgsql.NpgsqlException (0x80004005): Failed to connect to /var/run/postgresql/.s.PGSQL.5432 ---> System.Net.Sockets.SocketException (99): Cannot assign requested address

z tego co szukam i próbuje, to wygląda mi to jakby ten mój socket do postgresa nie działał. Nie wiem jak to sprawdzić czy on działa. Podobno powinien znajdować się w tym katalogu

$ cat /var/run/postgresql/.s.PGSQL.5432

ale cat: /var/run/postgresql/.s.PGSQL.5432: No such device or address

dlatego myśle, że może ten socket nie dziala? Jak to sprawdzić? Gdzie mój socket 😂😂😂

Poleceniem sudo psql -d bmw -U postgres mogę się zalogować do bazy na serwerze

Po zalogowaniu do bazy i wykonaniu polecenia show unix_socket_directories zwraca mi /var/run/postgresql

Macie może jakiś pomysł jak to rozwiązać ten problem albo jak inaczej połączyć się do bazy.
Dodam, że to dla środowiska produkcyjnego więc fajnie żeby to było zgodne ze sztuką ;p

Takie mam logi z postgresa, czyli ten plik tam powinien byc.. a go nie ma. Dodalem swojego usera ktorym jestem zalogowany do grupy uzytkownika postgres ale to nic nie zmienilo ja dalej tego pliku nie widze

2023-02-08 2130.967 UTC [182903] LOG: starting PostgreSQL 13.9 (Debian 13.9-0+deb11u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
2023-02-08 2130.968 UTC [182903] LOG: listening on IPv6 address "::1", port 5432
2023-02-08 2130.968 UTC [182903] LOG: listening on IPv4 address "127.0.0.1", port 5432
2023-02-08 2130.970 UTC [182903] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-02-08 2130.975 UTC [182905] LOG: database system was shut down at 2023-02-08 2130 UTC ????? mhh
2023-02-08 2130.981 UTC [182903] LOG: database system is ready to accept connections

Łącząc się w ten sposób psql -h /var/run/postgresql/.s.PGSQL.5432 -U postgres
mam błąd psql: error: could not connect to server: Not a directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432/.s.PGSQL.5432"?

ale tak dziala
psql -h /var/run/postgresql -U postgres

wg konfiguracji /etc/postgresql/10/main/postgresql.conf powinno byc dobrze raczej wszystko. To moze cos z tym moim uzytkonikiem na ktorym jestem zalogowany jest nie tak? Ale patrzylem i mam do tego katalogu co jest ten plik dostep

Albo cos z serwerem bazy jest zrabane i nie dziala 🤷‍♂️🤦‍♀️

2

Spróbuj zamiast IP w connections string wpisać host.docker.internal i podaj port na którym pracuje baza.

0
jurek1980 napisał(a):

Spróbuj zamiast IP w connections string wpisać host.docker.internal i podaj port na którym pracuje baza.

W sensie cos takiego?

"connectionString": "Host=host.docker.internal;Port=5432;Database=bmw;Username=postgres;Password=password"

i wtedy już bez tego volumes w docker compose?

à propos tego mojego podejścia z postu powyżej mam pewien trop. Mój connection string wygląda tam tak:

"connectionString": "Host=/var/run/postgresql;Database=bmw;Username=postgres;Password=password"

a z jakiegoś powodu w wyjątku mam, że

Failed to connect to /var/run/postgresql/.s.PGSQL.5432

zastanawiam się skąd się bierze ta końcówka .s.PGSQL.5432?

No bo jak na serwerze łączę się do bazy przez psql i socket czyli tak

psql -h /var/run/postgresql/.s.PGSQL.5432 -U postgres

mam błąd

psql: error: could not connect to server: Not a directory Is the server running locally and accepting connections on Unix domain socket /var/run/postgresql/.s.PGSQL.5432/.s.PGSQL.5432

ale tak już działa

psql -h /var/run/postgresql -U postgres

czyli wynika z tego jakby to było niepotrzebne .s.PGSQL.5432

No i też nie mam pojęcia czemu nie widzę tego socketa w tym katalogu. Podobno tam powinien być a go tam fizycznie nie ma..
Wg konfiguracji postgresa też tam powinien być

1
RideorDie napisał(a):

W sensie cos takiego?

"connectionString": "Host=host.docker.internal;Port=5432;Database=bmw;Username=postgres;Password=password"

i wtedy już bez tego volumes w docker compose?

Tak, tak jakbyś miał się łączyć do bazy przez sieć.

Co do doklejania to jak nie podasz portu to pewnie doklejany jest automatycznie port standardowy na poziomie frameworka.
W ramach testu uruchom sobie w dockerze jakiś pgadmin i się z niego połącz z bazy. https://hub.docker.com/r/dpage/pgadmin4/

BTW.
Nie do końca rozumiem czemu baza ma stać na hoście jak to ma być produkcja. Nie lepiej pójść w oddzielny serwer na bazę? Czy jak to jakaś chmura to baza dostarczona przez dostawcę.

1

Być może biblioteka której używasz nie ogarnia Unix domain socket i bezwzględnie oczekują hosta, stąd komunikat "Cannot assign requested address" Prześledź stack trace i zobacz czego oczekują funkcje i co dostają.

Inna sprawa, jeżeli pliku nie widać w kontenerze, to coś zostało źle zamontowane. Najlepiej sprawdź przez docker exec <nazwa_kontenera> ls -al /var/run/postgresql/ czy plik tam istnieje.

0
jurek1980 napisał(a):

Tak, tak jakbyś miał się łączyć do bazy przez sieć.

czyli wtedy pewnie też trzeba będzie zmienić coś w ustawieniach postgresa, żeby akceptował połączenia po sieci? Bo domyślnie to jest wyłączone

Z pg admin mogę spróbować. Mogę spróbować odpalić też apkę bezpośrednio na hoście i w connection stringu zostawić ten socket, wtedy odpadnie problem z volume.

nalik napisał(a):

Inna sprawa, jeżeli pliku nie widać w kontenerze, to coś zostało źle zamontowane. Najlepiej sprawdź przez docker exec <nazwa_kontenera> ls -al /var/run/postgresql/ czy plik tam istnieje.

nie sprawdzę tego bo kontener wywala zaraz przy starcie z wyjątkiem który wstawiłem.

No ale ja nie rozumiem, czemu ja fizycznie tego pliku (socketa) nie mam. On powinien być w momencie jak baza działa. Tak też ludzie piszą, go nie ma fizycznie. a w logach jest ze baza nasluguje na socket. I rzeczywiscie da sie zalogowac przez socket do bazy przez komente psql na serwerze tak jak pisałem ale w ten sposob
psql -h /var/run/postgresql -U postgres
tak nie dziala
psql -h /var/run/postgresql/.s.PGSQL.5432 -U postgres (a ta sama ścieżka robi się przez connection stringa i wydaje mi sie ze przez to nie moze sie polaczyc bo jest to .s.PGSQL.5432)

0
RideorDie napisał(a):
nalik napisał(a):

Inna sprawa, jeżeli pliku nie widać w kontenerze, to coś zostało źle zamontowane. Najlepiej sprawdź przez docker exec <nazwa_kontenera> ls -al /var/run/postgresql/ czy plik tam istnieje.

nie sprawdzę tego bo kontener wywala zaraz przy starcie z wyjątkiem który wstawiłem.

No ale ja nie rozumiem, czemu ja fizycznie tego pliku (socketa) nie mam. On powinien być w momencie jak baza działa. Tak też ludzie piszą, go nie ma fizycznie. a w logach jest ze baza nasluguje na socket. I rzeczywiscie da sie zalogowac przez socket do bazy przez komente psql na serwerze tak jak pisałem ale w ten sposob
psql -h /var/run/postgresql -U postgres
tak nie dziala
psql -h /var/run/postgresql/.s.PGSQL.5432 -U postgres (a ta sama ścieżka robi się przez connection stringa i wydaje mi sie ze przez to nie moze sie polaczyc bo jest to .s.PGSQL.5432)

Zmień entrypoint kontenera w docker-compose, najpierw wylistuj katalog, potem wykonaj oryginalny entrypoint.

Generalnie to wygląda, że psql -h przyjmuje katalog, a nie plik. To, że psql -h /var/run/postgresql -U postgres działa, sugeruje, że plik istnieje, ale nie wiesz, czy docker-compose go podmontował. Jak to sprawdzisz, to wykluczysz lub potwierdzisz jakąś opcję.

0
nalik napisał(a):

Zmień entrypoint kontenera w docker-compose, najpierw wylistuj katalog, potem wykonaj oryginalny entrypoint.

@nalik: A jak to zrobić? Nie jestem biegły z dockera :/

mam taki dockerfile

FROM mcr.microsoft.com/dotnet/sdk:7.0 as build-env
WORKDIR /src
COPY src/*.csproj .
RUN dotnet restore
COPY src .
RUN dotnet publish -c Release -o /publish

FROM mcr.microsoft.com/dotnet/aspnet:7.0 as runtime
WORKDIR /app
COPY --from=build-env /publish .
EXPOSE 80
ENTRYPOINT ["dotnet", "test.dll"]

a to mój compose


services:
  app:
    build:
      context: .
    ports:
      - 5000:80
    volumes:
      - /var/run/postgresql:/var/run/postgresql


1

Na przkład w ten sposób.

services:
  app:
    build:
      context: .
    entrypoint: sh -c "ls /var/run/postgresql; dotnet test.dll"
    ports:
      - 5000:80
    volumes:
      - /var/run/postgresql:/var/run/postgresql

0

Jest mały update odnośnie obecności tego pliku (socketa) na serwerze.

Komenda wypisujaca ukryte pliki ls -a /var/run/postgresql/ wypisuje tez ten plik (jak cos to zmienil sie port po przeinstalowalem postgresa)

ls -a /var/run/postgresql/
. .. .s.PGSQL.5433 .s.PGSQL.5433.lock 13-main.pg_stat_tmp 15-main.pid

ls /var/run/postgresql
13-main.pg_stat_tmp 15-main.pid

1

Udało się... Dziekuje wszystkim za pomoc. Problem polegal na tym ze niepoprawnie uruchamialem przeslany obraz na serwerze. Trzeba z -v uruchamiac.

sudo docker run -d -p 5000:80 -v /var/run/postgresql:/var/run/postgresql api blabla

1 użytkowników online, w tym zalogowanych: 0, gości: 1