Tehát van egy Nginx fut egy dokkoló konténerben, Van egy mysql fut a localhoston, Szeretnék csatlakozni a MySql belülről az én Nginx. A MySql a localhoston fut, és nem ad ki portot a külvilágnak, tehát a localhoston van kötve, nem a gép ip-címén.
Van-e mód arra, hogy a dokkoló konténeren belülről csatlakozzak ehhez a MySql-hez vagy bármilyen más programhoz a localhost-on?
Ez a kérdés különbözik a "Hogyan kapjuk meg a dokkoló host IP-címét a dokkoló konténeren belülről" annak a ténynek köszönhetően, hogy a dokkoló host IP-címe lehet a nyilvános IP vagy a hálózatban lévő privát IP, amely lehet, hogy nem érhető el a dokkoló konténeren belülről (úgy értem, nyilvános IP, ha az AWS-nél vagy valami másnál van elhelyezve). Még ha meg is van a docker host IP-címe, ez nem jelenti azt, hogy a konténeren belülről csatlakozhat a docker hosthoz az adott IP-cím alapján, mivel a docker hálózat lehet overlay, host, bridge, macvlan, none stb., ami korlátozza az IP-cím elérhetőségét.
Szerkesztés: Ha a Docker-for-mac vagy a Docker-for-Windows 18.03+ verziót használod, csak csatlakozz a mysql szolgáltatásodhoz a host.docker.internal
host használatával.
A Docker 18.09.3 óta ez nem működik Docker-for-Linuxon. Egy javítás került benyújtásra 2019. március 8-án, és remélhetőleg beolvad a kódbázisba. Addig is, a megoldás a qoomon's answer-ben leírt konténer használata.
Használja a --network="host"
t a docker run
parancsban, akkor a 127.0.0.0.1
a docker konténerben a docker hostra fog mutatni.
Megjegyzés: Ez a mód csak a Docker for Linuxon működik a dokumentáció szerint.
A Docker különböző hálózati módokat kínál a konténerek futtatásakor. A választott módtól függően másképp csatlakozna a dokkoló hoston futó MySQL-adatbázisához.
A Docker alapértelmezés szerint létrehoz egy docker0
nevű hidat. Mind a docker host, mind a docker konténerek IP-címmel rendelkeznek ezen a hídon.
Ha a Docker hoston beírjuk a sudo ip addr show docker0
parancsot, akkor a következő kimenetet kapjuk:
[vagrant@docker:~] $ sudo ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
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
inet6 fe80::5484:7aff:fefe:9799/64 scope link
valid_lft forever preferred_lft forever
Tehát itt a docker hostomnak a 172.17.42.1
IP-címe van a docker0
hálózati interfészen.
Most indítsunk el egy új konténert, és szerezzünk be rajta egy héjat: docker run --rm -it ubuntu:trusty bash
és a konténeren belül írjuk be az ip addr show eth0
parancsot, hogy megtudjuk, hogyan van beállítva a fő hálózati interfész:
root@e77f6a1b3740:/# ip addr show eth0
863: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 66:32:13:f0:f1:e3 brd ff:ff:ff:ff:ff:ff
inet 172.17.1.192/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::6432:13ff:fef0:f1e3/64 scope link
valid_lft forever preferred_lft forever
Itt a konténerem IP-címe a 172.17.1.192
. Most nézzük meg az útválasztási táblázatot:
root@e77f6a1b3740:/# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.17.42.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 * 255.255.0.0 U 0 0 0 eth0
Tehát a docker host 172.17.42.1
IP címe van beállítva alapértelmezett útvonalként, és elérhető a konténeredből.
root@e77f6a1b3740:/# ping 172.17.42.1
PING 172.17.42.1 (172.17.42.1) 56(84) bytes of data.
64 bytes from 172.17.42.1: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 172.17.42.1: icmp_seq=2 ttl=64 time=0.201 ms
64 bytes from 172.17.42.1: icmp_seq=3 ttl=64 time=0.116 ms
Alternatívaként futtathat egy docker konténert hálózati beállítások host
-ra állítva. Egy ilyen konténer megosztja a hálózati stacket a docker hosttal, és a konténer szempontjából a localhost
(vagy 127.0.0.0.1
) a docker hostra fog utalni.
Ne feledje, hogy a docker konténerben megnyitott minden port a docker hoston is meg fog nyílni. És mindezt anélkül, hogy a -p
vagy -P
docker run
opciót igényelné.
IP konfiguráció a docker hostomon:
[vagrant@docker:~] $ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
valid_lft forever preferred_lft forever
és egy docker konténerből host módban:
[vagrant@docker:~] $ docker run --rm -it --network=host ubuntu:trusty ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
valid_lft forever preferred_lft forever
Mint látható, mind a docker host, mind a docker konténer pontosan ugyanazt a hálózati interfészt használja, és így ugyanazzal az IP-címmel rendelkezik.
Ahhoz, hogy a dokkoló hoston futó MySQL-t konténerekből bridge módban elérjük, meg kell győződnünk arról, hogy a MySQL szolgáltatás a 172.17.42.1
IP-címen hallgatja a kapcsolatokat.
Ehhez győződjön meg arról, hogy a MySQL konfigurációs fájljában (my.cnf) a bind-address = 172.17.42.1
vagy a bind-address = 0.0.0.0.0
szerepel.
Ha be kell állítanod egy környezeti változót az átjáró IP-címével, akkor a következő kódot futtathatod egy konténerben :
export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')
majd az alkalmazásban használja a DOCKER_HOST_IP
környezeti változót a MySQL-hez való kapcsolat megnyitásához.
Figyelem: ha a bind-address = 0.0.0.0.0
változót használja, akkor a MySQL szerver minden hálózati interfészen figyelni fogja a kapcsolatokat. Ez azt jelenti, hogy a MySQL szerver elérhető az internetről ; győződjön meg róla, hogy a tűzfalszabályokat ennek megfelelően állította be.
2. megjegyzés: ha a bind-address = 172.17.42.1
címet használja, a MySQL szervere nem fog figyelni a 127.0.0.1
címre irányuló kapcsolatokra. A docker hoston futó folyamatoknak, amelyek csatlakozni szeretnének a MySQL-hez, a 172.17.42.1
IP-címet kell használniuk.
Ahhoz, hogy a dokkoló hoston futó MySQL-t a konténerekből host módban érje el, a MySQL konfigurációjában megtarthatja a bind-address = 127.0.0.0.1
címet, és csak a 127.0.0.0.1
címre kell csatlakoznia a konténerekből:
[vagrant@docker:~] $ docker run --rm -it --network=host mysql mysql -h 127.0.0.1 -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 36
Server version: 5.5.41-0ubuntu0.14.04.1 (Ubuntu)
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
jegyzet: Használd a mysql -h 127.0.0.0.1
-t és ne a mysql -h localhost
-t; különben a MySQL kliens egy unix socket segítségével próbálna csatlakozni.
Ez működött nekem egy NGINX/PHP-FPM veremben anélkül, hogy bármilyen kódot vagy hálózatot érintene, ahol az alkalmazás csak arra számít, hogy képes legyen csatlakozni a localhost
-hoz.
Mount mysqld.sock
a hostról a konténer belsejébe.
Keresse meg a mysql.sock fájl helyét a mysql-t futtató állomáson:
netstat -ln | awk '/mysql(.*)?\.sock/ { print $9 }'
Mountoljuk ezt a fájlt oda, ahová a dokkolóban várjuk:
docker run -v /hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock
A mysqld.sock lehetséges helyei:
/tmp/mysqld.sock
/var/run/mysqld/mysqld.sock
/var/lib/mysql/mysql.sock
/Applications/MAMP/tmp/mysql/mysql.sock # if running via MAMP
Nem értek egyet Thomasleveil válaszával.
A mysql 172.17.42.1-re való kötése megakadályozza, hogy más, az adatbázist használó programok elérjék az adott állomáson lévő adatbázist. Ez csak akkor fog működni, ha az összes adatbázis-felhasználó dokkolva van.
Ha a mysql-t 0.0.0.0.0-ra kötjük, az megnyitja a db-t a külvilág felé, ami nem csak nagyon rossz dolog, de ellentétes is azzal, amit az eredeti kérdés szerzője szeretne. Kifejezetten azt mondja "A MySql a localhoston fut, és nem ad ki portot a külvilágnak, ezért a localhoston köti meg"
Az ivant megjegyzésére válaszolva
"Miért nem köti a mysql-t a docker0-hoz is?"
Ez nem lehetséges. A mysql/mariadb dokumentáció kifejezetten azt mondja, hogy nem lehet több interfészhez kötni. Csak 0, 1 vagy az összes interfészhez lehet kötni.
Következtetésként NEM találtam semmilyen módot arra, hogy a (csak localhost) adatbázist elérjem a hoston egy docker konténerből. Ez határozottan egy nagyon-nagyon gyakori mintának tűnik, de nem tudom, hogyan lehet ezt megcsinálni.