Izinkan kontainer buruh pelabuhan untuk terhubung ke database postgres lokal / host

153

Saya baru-baru ini bermain-main dengan Docker dan QGIS dan telah menginstal sebuah wadah dengan mengikuti instruksi dalam tutorial ini .

Semuanya bekerja dengan baik, meskipun saya tidak dapat terhubung ke database localhost postgres yang berisi semua data GIS saya. Saya membayangkan ini karena database postgres saya tidak dikonfigurasi untuk menerima koneksi jarak jauh dan telah mengedit file konfigurasi postgres untuk memungkinkan koneksi jarak jauh menggunakan instruksi dalam artikel ini .

Saya masih mendapatkan pesan kesalahan ketika saya mencoba dan terhubung ke database saya yang menjalankan QGIS di Docker: tidak dapat terhubung ke server: Connection refused Is the server running on host "localhost" (::1) and accepting TCP/IP connections to port 5433? Server postgres sedang berjalan, dan saya telah mengedit file pg_hba.conf saya untuk memungkinkan koneksi dari berbagai Alamat IP (172.17.0.0/32). Saya sebelumnya menanyakan alamat IP dari kontainer buruh pelabuhan yang menggunakan docker psdan meskipun alamat IP berubah, sejauh ini selalu berada di kisaran 172.17.0.x

Ada ide mengapa saya tidak dapat terhubung ke database ini? Mungkin sesuatu yang sangat sederhana yang saya bayangkan!

Saya menjalankan Ubuntu 14.04; Postgres 9.3

marty_c
sumber

Jawaban:

159

TL; DR

  1. Gunakan 172.17.0.0/16sebagai rentang alamat IP, bukan 172.17.0.0/32.
  2. Jangan gunakan localhostuntuk terhubung ke database PostgreSQL di host Anda, tetapi gunakan IP host. Untuk menjaga agar wadah tetap portabel, mulai wadah dengan --add-host=database:<host-ip>bendera dan gunakan databasesebagai nama host untuk menghubungkan ke PostgreSQL.
  3. Pastikan PostgreSQL dikonfigurasi untuk mendengarkan koneksi di semua alamat IP, tidak hanya di localhost. Cari pengaturan listen_addressesdi file konfigurasi PostgreSQL, biasanya ditemukan di /etc/postgresql/9.3/main/postgresql.conf(kredit untuk @DazmoNorton).

Versi panjang

172.17.0.0/32bukan rentang alamat IP, tetapi satu alamat (namanya 172.17.0.0). Tidak ada container Docker yang akan mendapatkan alamat itu, karena ini adalah alamat jaringan dari docker0antarmuka Docker bridge ( ).

Ketika Docker dimulai, itu akan membuat antarmuka jaringan jembatan baru, yang dapat Anda lihat dengan mudah saat memanggil ip a:

$ ip a
...
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever

Seperti yang Anda lihat, dalam kasus saya, docker0antarmuka memiliki alamat IP 172.17.42.1dengan netmask /16(atau 255.255.0.0). Artinya alamat jaringan adalah 172.17.0.0/16.

Alamat IP ditetapkan secara acak, tetapi tanpa konfigurasi tambahan apa pun, itu akan selalu ada di 172.17.0.0/16jaringan. Untuk setiap kontainer Docker, alamat acak dari kisaran itu akan ditetapkan.

Artinya, jika Anda ingin memberikan akses dari semua kemungkinan penampung ke database Anda, gunakan 172.17.0.0/16.

helmbert
sumber
1
hai terima kasih atas komentar Anda. Saya telah mengubah saya pg_hba.confke alamat yang Anda sarankan, tetapi masih mendapatkan pesan kesalahan koneksi yang sama setelah berhenti dan memulai ulang layanan postgres. Saya telah menambahkan baris di bawah koneksi ipv4 saya - apakah ada tempat lain yang harus saya tambahkan alamat yang Anda sarankan? Atau, di aplikasi QGIS saya yang berjalan di Docker, apakah saya perlu mengubah info koneksi postgres? Misalnya, jika saya menghubungkan dari dalam kontainer buruh pelabuhan apakah tuan rumah masih 'localhost'?
marty_c
Ah, itu poin penting. Tidak, localhostbukan sistem host di dalam container Docker Anda. Coba sambungkan ke alamat IP publik sistem host. Untuk menjaga agar container tetap portabel, Anda juga dapat memulai container dengan --add-host=database:<host-ip>dan cukup gunakan databasesebagai nama host untuk menghubungkan ke host PostgreSQL Anda dari dalam container Docker.
helmbert
6
Saya butuh satu potong lagi. Saya juga harus mengedit /etc/postgresql/9.3/main/postgresql.confdan menambahkan eth0alamat IP server saya ke listen_addresses. Secara default hanya listen_addressesmemiliki postgres mengikat localhost.
Dzamo Norton
@DzamoNorton, terima kasih atas petunjuknya! Saya memperbarui jawaban saya sesuai.
helmbert
@helmbert host-ipadalah alamat ip dari mesin virtual atau kontainer buruh pelabuhan?
Tn.
61

Solusi Docker untuk Mac

17.06 dan seterusnya

Berkat komentar @Birchlabs, sekarang jauh lebih mudah dengan nama DNS khusus Mac yang tersedia :

docker run -e DB_PORT=5432 -e DB_HOST=docker.for.mac.host.internal

Dari 17.12.0-cd-mac46, docker.for.mac.host.internalsebaiknya digunakan sebagai pengganti docker.for.mac.localhost. Lihat catatan rilis untuk detailnya.

Versi yang lebih lama

Jawaban @ helmbert menjelaskan masalahnya dengan baik. Tetapi Docker untuk Mac tidak mengekspos jaringan jembatan , jadi saya harus melakukan trik ini untuk mengatasi batasannya:

$ sudo ifconfig lo0 alias 10.200.10.1/24

Buka /usr/local/var/postgres/pg_hba.confdan tambahkan baris ini:

host    all             all             10.200.10.1/24            trust

Buka /usr/local/var/postgres/postgresql.confdan edit perubahan listen_addresses:

listen_addresses = '*'

Muat ulang layanan dan luncurkan penampung Anda:

$ PGDATA=/usr/local/var/postgres pg_ctl reload
$ docker run -e DB_PORT=5432 -e DB_HOST=10.200.10.1 my_app 

Apa yang dilakukan solusi ini pada dasarnya sama dengan jawaban @ helmbert, tetapi menggunakan alamat IP yang dilampirkan lo0alih-alih docker0antarmuka jaringan.

baxang
sumber
3
Apakah ini masih berlaku per 4 April 2017?
Petrus Theron
Saya suka cara ini yang tidak akan mengekspos database. BTW, bisakah saya menggunakan ini di CentOS? Saya mendapat kesalahan: alias: Host tidak dikenal ketika saya mencoba menggunakan perintah alias yang Anda berikan.
Tsung Goh
6
Ada cara yang lebih baik di macOS, mulai Docker 17.06.0-rc1-ce-mac13 (1 Juni 2017). kontainer mengenali tuan rumah docker.for.mac.localhost. ini adalah IP mesin host Anda. mencari entri di database host penampung seperti ini: docker run alpine /bin/sh -c 'getent hosts docker.for.mac.localhost'
Birchlabs
@Birchlabs Ini sangat mengagumkan!
qqilihq
5
Sepertinya sudah berubah host.docker.internalsejak 18.03, opsi lain masih tersedia tetapi tidak digunakan lagi ( Sumber ).
gseva
48

Solusi Sederhana untuk mac:

Versi terbaru dari buruh pelabuhan (18.03) menawarkan solusi penerusan port bawaan. Di dalam kontainer buruh pelabuhan Anda cukup mengatur host db ke host.docker.internal. Ini akan diteruskan ke host tempat kontainer buruh pelabuhan berjalan.

Dokumentasi untuk ini ada di sini: https://docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host

Chris
sumber
3
Sejauh ini, ini adalah jawaban terbaik! jauh lebih mudah dan bagaimana seharusnya.
bjm88
2
adalah host.docker.internalterbatas pada Mac hanya?
Dragas
@Dragas menurut dokumen itu akan "tidak berfungsi di luar Mac", tetapi nama DNS yang sama disebutkan dalam dokumen untuk Docker untuk Windows, jadi saya pikir itu terbatas pada "Docker untuk ...". Either way itu hanya pengembangan: Anda tidak dimaksudkan untuk mengirimkan gambar buruh pelabuhan yang menggunakan ini.
Rhubarb
Hanya bekerja dengan windows dan mac. Dalam kasus saya, ubuntu tidak berfungsi
Azri Zakaria
20

Solusi sederhana

Tambahkan saja --network=hostke docker run. Itu saja!

Dengan cara ini kontainer akan menggunakan jaringan host, jadi localhostdan 127.0.0.1akan mengarah ke host (secara default mereka menunjuk ke sebuah kontainer). Contoh:

docker run -d --network=host \
  -e "DB_DBNAME=your_db" \
  -e "DB_PORT=5432" \
  -e "DB_USER=your_db_user" \
  -e "DB_PASS=your_db_password" \
  -e "DB_HOST=127.0.0.1" \
  --name foobar foo/bar
Max Malysh
sumber
3
Hati-hati! Solusi ini, yang menurut saya benar, tidak berfungsi untuk macOS. Jangan buang waktu Anda mencoba mencari tahu mengapa itu tidak berhasil. Kunjungi
jfcorugedo
1
Bekerja di Debian. Mencoba mengubah postgresql.conf dan pg_hba.conf tetapi ini lebih sederhana dan lebih cepat.
frmbelz
6

Solusi yang diposting di sini tidak berfungsi untuk saya. Oleh karena itu, saya memposting jawaban ini untuk membantu seseorang yang menghadapi masalah serupa.

OS: Ubuntu 18
PostgreSQL: 9.5 (Di-host di Ubuntu)
Docker: Aplikasi Server (yang terhubung ke PostgreSQL)

Saya menggunakan docker-compose.yml untuk membangun aplikasi.

LANGKAH 1: Silakan tambahkanhost.docker.internal:<docker0 IP>

version: '3'
services:
  bank-server:
    ...
    depends_on:
      ....
    restart: on-failure
    ports:
      - 9090:9090
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

Untuk menemukan IP buruh pelabuhan i.e. 172.17.0.1 (in my case)Anda dapat menggunakan:

$> ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255

ATAU

$> ip a
1: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

LANGKAH 2: Di postgresql.conf, ubah listen_addresses menjadilisten_addresses = '*'

LANGKAH 3: Di pg_hba.conf, tambahkan baris ini

host    all             all             0.0.0.0/0               md5

LANGKAH 4: Sekarang restart layanan postgresql menggunakan,sudo service postgresql restart

LANGKAH 5: Silakan gunakan host.docker.internalnama host untuk menghubungkan database dari Aplikasi Server.
Ex:jdbc:postgresql://host.docker.internal:5432/bankDB

Nikmati!!

singhpradeep
sumber
3

untuk docker-compose kamu bisa coba tambahkan saja

network_mode: "host"

contoh:

version: '2'
services:
  feedx:
    build: web
    ports:
    - "127.0.0.1:8000:8000"
    network_mode: "host"

https://docs.docker.com/compose/compose-file/#network_mode

Sarath Ak
sumber
4
menambahkan networkd_mode ke host memutuskan koneksi antara kontainer lain
Bawantha
2

Di Ubuntu:

Pertama Anda harus memeriksa apakah port Database Docker tersedia di sistem Anda dengan mengikuti perintah -

sudo iptables -L -n

Contoh OUTPUT:

Chain DOCKER (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.2           tcp dpt:3306
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.3           tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.3           tcp dpt:22

Berikut 3306digunakan sebagai Docker Database Port pada 172.17.0.2 IP, Jika port ini tidak tersedia Jalankan perintah berikut -

sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT

Sekarang, Anda dapat dengan mudah mengakses Database Docker dari sistem lokal Anda dengan mengikuti konfigurasi

  host: 172.17.0.2 
  adapter: mysql
  database: DATABASE_NAME
  port: 3307
  username: DATABASE_USER
  password: DATABASE_PASSWORD
  encoding: utf8

Di CentOS:

Pertama Anda harus memeriksa apakah port Database Docker Tersedia di firewall Anda dengan mengikuti perintah -

sudo firewall-cmd --list-all

Contoh OUTPUT:

  target: default
  icmp-block-inversion: no
  interfaces: eno79841677
  sources: 
  services: dhcpv6-client ssh
  **ports: 3307/tcp**
  protocols: 
  masquerade: no
  forward-ports: 
  sourceports: 
  icmp-blocks: 
  rich rules:

Berikut 3307digunakan sebagai Docker Database Port pada 172.17.0.2 IP, Jika port ini tidak tersedia Jalankan perintah berikut -

sudo firewall-cmd --zone=public --add-port=3307/tcp

Di server, Anda dapat menambahkan port secara permanen

sudo firewall-cmd --permanent --add-port=3307/tcp
sudo firewall-cmd --reload

Sekarang, Anda dapat dengan mudah mengakses Database Docker dari sistem lokal Anda dengan konfigurasi di atas.

Sanaulla
sumber
2
Saya tahu ini sudah tua tetapi Sekarang, Anda dapat dengan mudah mengakses Database Docker dari sistem lokal Anda dengan mengikuti konfigurasi - Anda memiliki cara yang salah. Dia memiliki database lokal, dan aplikasi buruh pelabuhan mencoba untuk menghubungkan ke db lokal itu bukan sebaliknya
Craicerjack
1

Untuk mengatur sesuatu yang sederhana yang memungkinkan koneksi Postgresql dari container docker ke localhost saya, saya menggunakan ini di postgresql.conf:

listen_addresses = '*'

Dan menambahkan pg_hba.conf ini:

host    all             all             172.17.0.0/16           password

Kemudian lakukan restart. Klien saya dari kontainer buruh pelabuhan (yang berada di 172.17.0.2) kemudian dapat terhubung ke Postgresql yang berjalan di localhost saya menggunakan host: kata sandi, database, nama pengguna dan kata sandi.

Harlin
sumber
0

Satu hal lagi yang diperlukan untuk penyiapan saya adalah menambahkan

172.17.0.1  localhost

untuk /etc/hosts

sehingga Docker akan menunjuk 172.17.0.1sebagai nama host DB, dan tidak bergantung pada ip luar yang berubah untuk menemukan DB. Semoga ini bisa membantu orang lain dengan masalah ini!

Mikko Pöri
sumber
15
Ini adalah solusi yang buruk. Localhost biasanya mengarah ke 127.0.0.1. Mengubahnya mungkin memiliki konsekuensi yang tidak diinginkan, bahkan jika dalam kasus khusus ini berhasil.
Alex
2
Cara yang lebih baik adalah dengan menyiapkan databasehost --add-host=database:172.17.0.1saat menjalankan penampung. Kemudian arahkan aplikasi Anda ke host tersebut. Ini menghindari hard-coding alamat IP di dalam wadah.
jaredsk
1
yang --add-host=database:172.17.0.1lebih disukai
Luis Martins
-3

Solusi lain adalah volume layanan, Anda dapat menentukan volume layanan dan memasang direktori Data PostgreSQL host di volume itu. Lihat file tulis yang diberikan untuk mengetahui detailnya.

version: '2'
services:
  db:   
    image: postgres:9.6.1
    volumes:
      - "/var/lib/postgresql/data:/var/lib/postgresql/data" 
    ports:
      - "5432:5432"

Dengan melakukan ini, layanan PostgreSQL lain akan berjalan di bawah wadah tetapi menggunakan direktori data yang sama yang digunakan oleh layanan PostgreSQL host.

Hrishi
sumber
1
Ini mungkin akan menyebabkan konflik penulisan dengan host layanan PostgreSQL yang sedang berjalan
Petrus Theron
Saya pikir menghentikan layanan host akan menyelesaikan masalah dalam kasus itu.
Hrishi