Bir docker konteyneri içinde çalışan bir Nginx'im var, localhost üzerinde çalışan bir mysql'im var, MySql'e Nginx'im içinden bağlanmak istiyorum. MySql localhost üzerinde çalışıyor ve dış dünyaya bir bağlantı noktası göstermiyor, bu nedenle makinenin ip adresine bağlı değil, localhost'a bağlı.
Bu MySql'e veya localhost'taki başka bir programa bu docker konteynerinden bağlanmanın herhangi bir yolu var mı?
Bu soru "Bir docker konteynerinin içinden docker ana bilgisayarının IP adresi nasıl alınır" sorusundan farklıdır, çünkü docker ana bilgisayarının IP adresi, docker konteynerinin içinden erişilebilen veya erişilemeyen ağdaki genel IP veya özel IP olabilir (AWS'de veya başka bir yerde barındırılıyorsa genel IP'yi kastediyorum). Docker ana bilgisayarının IP adresine sahip olsanız bile, Docker ağınız bu IP adresinin erişilebilirliğini kısıtlayan overlay, host, bridge, macvlan, none vb. olabileceğinden, bu IP adresi verilen konteyner içinden docker ana bilgisayarına bağlanabileceğiniz anlamına gelmez.
Düzenleme: Docker-for-mac veya Docker-for-Windows 18.03+ kullanıyorsanız, mysql hizmetinize host.docker.internal
ana bilgisayarını kullanarak bağlanmanız yeterlidir.
Docker 18.09.3'ten itibaren bu özellik Docker-for-Linux üzerinde çalışmamaktadır. 8 Mart 2019'da bir düzeltme gönderilmiştir ve umarız kod tabanına birleştirilir. O zamana kadar, qoomon'un cevabı'de açıklandığı gibi bir konteyner kullanmak geçici bir çözümdür.
Docker runkomutunuzda
--network="host"kullanın, ardından docker konteynerinizdeki
127.0.0.1` docker hostunuzu gösterecektir.
Not: Bu mod yalnızca Linux için Docker üzerinde çalışır belgelere göre.
Docker, konteynerleri çalıştırırken farklı ağ modları sunar. Seçtiğiniz moda bağlı olarak, docker ana bilgisayarında çalışan MySQL veritabanınıza farklı şekilde bağlanacaksınız.
Docker varsayılan olarak docker0
adında bir köprü oluşturur. Hem docker ana bilgisayarının hem de docker konteynerlerinin bu köprü üzerinde bir IP adresi vardır.
Docker ana bilgisayarında, sudo ip addr show docker0
yazın, aşağıdaki gibi bir çıktı elde edeceksiniz:
[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
Yani burada docker hostumun docker0
ağ arayüzünde 172.17.42.1
IP adresi var.
Şimdi yeni bir konteyner başlatın ve üzerine bir kabuk yerleştirin: docker run --rm -it ubuntu:trusty bashve konteyner içinde ana ağ arayüzünün nasıl kurulduğunu keşfetmek için
ip addr show eth0` yazın:
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
Burada konteynerimin IP adresi 172.17.1.192
dir. Şimdi yönlendirme tablosuna bakın:
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
Böylece docker ana bilgisayarının IP Adresi 172.17.42.1
varsayılan rota olarak ayarlanır ve konteynerinizden erişilebilir.
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
Alternatif olarak ağ ayarları host
olarak ayarlanmış ile bir docker konteyneri çalıştırabilirsiniz. Böyle bir konteyner ağ yığınını docker host ile paylaşacaktır ve konteyner açısından localhost
(veya 127.0.0.1
) docker host'a atıfta bulunacaktır.
Docker konteynerinizde açılan herhangi bir portun docker ana bilgisayarında da açılacağını unutmayın. Ve bu -p
veya -P
docker run
seçeneği gerektirmeden.
Docker ana bilgisayarımdaki IP yapılandırması:
[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
ve host modunda bir docker konteynerinden:
[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
Gördüğünüz gibi hem docker host hem de docker container aynı ağ arayüzünü paylaşıyor ve bu nedenle aynı IP adresine sahip.
Docker ana bilgisayarında çalışan MySQL'e köprü modundaki konteynerlerden erişmek için MySQL servisinin 172.17.42.1
IP adresindeki bağlantıları dinlediğinden emin olmanız gerekir.
Bunu yapmak için MySQL yapılandırma dosyanızda (my.cnf) bind-address = 172.17.42.1
ya da bind-address = 0.0.0.0
olduğundan emin olun.
Ağ geçidinin IP adresini içeren bir ortam değişkeni ayarlamanız gerekiyorsa, aşağıdaki kodu bir kapsayıcıda çalıştırabilirsiniz:
export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')
ardından uygulamanızda, MySQL bağlantısını açmak için DOCKER_HOST_IP
ortam değişkenini kullanın.
Not: bind-address = 0.0.0.0
kullanırsanız MySQL sunucunuz tüm ağ arayüzlerindeki bağlantıları dinleyecektir. Bu, MySQL sunucunuza İnternet'ten erişilebileceği anlamına gelir; güvenlik duvarı kurallarını buna göre ayarladığınızdan emin olun.
Not 2: bind-address = 172.17.42.1
kullanırsanız MySQL sunucunuz 127.0.0.1
ile yapılan bağlantıları dinlemeyecektir. MySQLe bağlanmak isteyen docker host üzerinde çalışan prosesler
172.17.42.1` IP adresini kullanmak zorunda kalacaklardır.
Docker ana bilgisayarında çalışan MySQL'e host modunda konteynerlerden erişmek için MySQL yapılandırmanızda bind-address = 127.0.0.1
i tutabilirsiniz ve tek yapmanız gereken konteynerlerinizden 127.0.0.1
e bağlanmaktır:
[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>
Not: mysql -h localhost
değil mysql -h 127.0.0.1
kullanın; aksi takdirde MySQL istemcisi bir unix soketi kullanarak bağlanmaya çalışacaktır.
Bu, uygulamanın sadece localhost
a bağlanabilmeyi beklediği herhangi bir koda veya ağa dokunmadan bir NGINX/PHP-FPM yığınında benim için çalıştı
Ana bilgisayardan konteynerin içine mysqld.sock
dosyasını bağlayın.
mysql.sock dosyasının mysql çalıştıran ana bilgisayardaki konumunu bulun:
netstat -ln | awk '/mysql(.*)?\.sock/ { print $9 }'
Bu dosyayı docker'da beklenen yere monte edin:
docker run -v /hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock
mysqld.sock'un olası konumları:
/tmp/mysqld.sock
/var/run/mysqld/mysqld.sock
/var/lib/mysql/mysql.sock
/Applications/MAMP/tmp/mysql/mysql.sock # if running via MAMP
Thomasleveil'in cevabına katılmıyorum.
mysql'i 172.17.42.1'e bağlamak, ana bilgisayardaki veritabanını kullanan diğer programların ona ulaşmasını engelleyecektir. Bu yalnızca tüm veritabanı kullanıcılarınız dockerize edilmişse işe yarayacaktır.
Mysql'i 0.0.0.0'a bağlamak db'yi dış dünyaya açacaktır, bu sadece yapılacak çok kötü bir şey değil, aynı zamanda orijinal soru yazarının yapmak istediğine de aykırıdır. Açıkça diyor ki "MySql localhost üzerinde çalışıyor ve dış dünyaya bir port açmıyor, bu yüzden localhost'a bağlı"
ivant'ın yorumuna cevap vermek gerekirse
"Neden mysql'i docker0'a da bağlamıyorsunuz? "
Bu mümkün değildir. mysql/mariadb belgeleri açıkça birden fazla arayüze bağlanmanın mümkün olmadığını söylemektedir. Yalnızca 0, 1 veya tüm arayüzlere bağlayabilirsiniz.
Sonuç olarak, bir docker konteynerinden ana bilgisayardaki (yalnızca localhost) veritabanına ulaşmanın herhangi bir yolunu BULAMADIM. Bu kesinlikle çok çok yaygın bir model gibi görünüyor, ancak nasıl yapılacağını bilmiyorum.