Docker konteynerinin içinden, makinenin yerel ana bilgisayarına nasıl bağlanabilirim?


1449

Bu yüzden bir docker konteyner içinde çalışan bir Nginx var, localhost üzerinde çalışan bir mysql var, benim Nginx içinde MySql bağlanmak istiyorum. MySql localhost üzerinde çalışıyor ve bir bağlantı noktasını dış dünyaya maruz bırakmıyor, bu yüzden localhost'a bağlı, makinenin ip adresine bağlı değil.

Bu MySql'e veya localhost'taki başka bir programa bu docker konteynerinden bağlanmanın herhangi bir yolu var mı?

Bu soru, docker ana bilgisayarının IP adresinin ağdaki genel IP veya ağdaki olabilecek veya olabilecek özel IP olabilmesi nedeniyle "Docker ana bilgisayarının IP adresini bir docker kapsayıcısından nasıl alırsınız" dan farklıdır. docker kapsayıcısından ulaşılamaz (AWS'de barındırılıyorsa genel IP anlamına gelir). Docker ana bilgisayarının IP adresine sahip olsanız bile, Docker ağınızın bindirme, ana bilgisayar, köprü, macvlan, hiçbiri vb. Olabileceğinden, IP adresinin konteyner içinden docker ana bilgisayarına bağlanabileceğiniz anlamına gelmez. IP adresi.


Neden mysql'i docker0'a da bağlamıyorsunuz?
ivant

2
Windows Machine için: - $ docker run -d --name MyWebServer -P httpd
S


Olmadan network: hostbir konteynerden ana bilgisayara geri dönemezsiniz. Yalnızca konteynere ev sahipliği yapın. Kapların arkasındaki ana ideoloji budur. Hem kararlılık hem de güvenlik nedeniyle izole edilmiştir.
FreeSoftwareServers

Yanıtlar:


1969

Düzenle: Eğer kullanıyorsanız Docker-for-mac veya Docker-için Windows 18.03+, sadece ev sahibi kullanarak MySQL hizmetine bağlanmak host.docker.internal(yerine 127.0.0.1bağlantı dizesinde).

Docker 18.09.3'ten itibaren, bu, Linux için Docker'da çalışmaz. 8 Mart 2019'da bir düzeltme gönderildi ve umarım kod tabanıyla birleştirilecek. O zamana kadar bir çözüm, qoomon'un cevabında açıklandığı gibi bir kap kullanmaktır .

2020-01: bazı ilerlemeler kaydedildi . Her şey yolunda giderse, bu Docker 20.04'e inmeli


TLDR

Kullan --network="host"senin de docker rundaha sonra, komuta 127.0.0.1senin liman işçisi konak işaret olacaktır liman işçisi kap içinde.

Not: Bu mod yalnızca Linux için Docker'da çalışır, , belgelere göre .


Docker konteyneri ağ modları hakkında not

Docker teklifleri kapsayıcıları çalıştırırken farklı ağ modları . Seçtiğiniz moda bağlı olarak, docker ana bilgisayarında çalışan MySQL veritabanınıza farklı bağlanırsınız.

docker run --network = "köprü" (varsayılan)

Docker adlı bir köprü oluşturur docker0 varsayılan olarak . Hem docker ana bilgisayarında hem de docker kapsayıcılarında bu köprüde bir IP adresi bulunur.

Docker ana bilgisayarına şöyle sudo ip addr show docker0bir çıktıya sahip olacağınızı yazın :

[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 benim liman işçisi ana bilgisayar IP adresi vardır 172.17.42.1üzerindedocker0 ağ arayüzünde .

Şimdi yeni bir kapsayıcı başlatın ve üzerine bir kabuk alın: docker run --rm -it ubuntu:trusty bashve ip addr show eth0ana ağ arayüzünün nasıl kurulduğunu öğrenmek için kapsayıcı türü içinde :

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 kabımın IP adresi var 172.17.1.192. Ş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.1varsayılan yol olarak ayarlanır ve kapsayıcıdan 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

docker run --network = "ana bilgisayar"

Alternatif olarak, ağ ayarları olarak ayarlanmışhost bir docker kapsayıcısı çalıştırabilirsiniz . Böyle bir kap, ağ yığınını liman işçisini barındıran ve kapsayıcı açısından paylaşacaktır localhost(veya127.0.0.1 ) yükleyici ana bilgisayarına atıfta bulunacaktır.

Docker kabınızda açılan tüm bağlantı noktalarının docker ana bilgisayarında açılacağını unutmayın. Ve bu, veya seçeneğine ihtiyaç duymadan-p-P docker run .

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 ana bilgisayar kipindeki docker kapsayıcısından :

[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 ana makinesi hem de docker konteyneri aynı ağ arayüzünü paylaşır ve aynı IP adresine sahiptir.


Kapsayıcılardan MySQL'e bağlanma

köprü modu

Docker ana bilgisayarında çalışan MySQL'e köprü kipindeki kaplardan erişmek için, MySQL hizmetinin ağ bağlantılarını dinlediğinden emin olmanız gerekir.172.17.42.1 IP adresindeki .

Bunu yapmak için, emin olun ya bind-address = 172.17.42.1yabind-address = 0.0.0.0 için MySQL yapılandırma dosyanızın (my.cnf) içinde .

Ağ geçidinin IP adresiyle bir ortam değişkeni ayarlamanız gerekirse, bir kapta aşağıdaki kodu çalıştırabilirsiniz:

export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')

uygulamanızda DOCKER_HOST_IPMySQL bağlantısını açmak için ortam değişkenini kullanın.

Not:bind-address = 0.0.0.0 MySQL sunucunuzu kullanırsanız tüm ağ arayüzlerindeki bağlantıları dinler. 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 MySQL sunucunuzu kullanıyorsanız , yapılan bağlantıları dinlemez 127.0.0.1. Docker ana bilgisayarında MySQL'e bağlanmak isteyecek işlemlerin172.17.42.1 IP adresini .

ana bilgisayar modu

Docker ana bilgisayarında çalışan MySQL'e ana makine modunda kapsayıcılardan erişmek bind-address = 127.0.0.1için MySQL yapılandırmanızda kalabilir ve tek yapmanız gereken 127.0.0.1kaplarınızdan 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: kullanın mysql -h 127.0.0.1ve değil mysql -h localhost; aksi takdirde MySQL istemcisi bir unix soketi kullanarak bağlanmaya çalışır.


8
Bu kadar ayrıntılı bir cevap için teşekkürler! Topladığım kadarıyla, hosthost'u kullanmak bu işlevi localhost üzerinden almanın tek yoludur. Denemedim ama kapları kendi köprüleri üzerinden bağlamak için ayrı bir ağ oluşturabileceğinizi varsayabilirim.
Ben

26
OSX kullanıcıları için not: "docker-machine ssh default" kullanarak önce docker sanal makinenize (boot2docker) giriş yapın, sonra "sudo ip addr show docker0" komutunu çalıştırın. Oradan Thomas'ın talimatları ile devam edin.
Charlie Dalsass

30
Mac için Docker kullanıyorum ve artık 172.17.42.1 yok, artık docker0 yok. Ağ geçidi olarak 172.17.0.1 idi ve hatta olamaztelnet 172.17.0.1 3306
zx1986

26
Mysql soketini böyle ağ oluşturmak yerine kaba monte edebilirsiniz -v /var/run/mysqld/mysqld.sock:/tmp/mysql.sock.
chx

8
Birisi Mac'te Docker'ı çalıştırırken ve boot2docker'ı bu şekilde kullanmadığında docker0 arabirimi olmadığında durumu ele alabilir mi?
TheJKFever

350

MacOS ve Windows için

Docker v 18.03 ve üstü (21 Mart 2018'den beri)

Dahili IP adresinizi kullanın veya özel DNS adına bağlanın host.docker.internal ana bilgisayar tarafından kullanılan dahili IP adresine çözümlenecek .

Bekleyen Linux desteği https://github.com/docker/for-linux/issues/264

Docker'ın önceki sürümlerine sahip MacOS

Mac için Docker v 17.12 - v 18.02

Yukarıdaki ile aynı ama docker.for.mac.host.internalbunun yerine kullanın.

Mac için Docker v 17.06 - v 17.11

Yukarıdaki ile aynı ama docker.for.mac.localhostbunun yerine kullanın.

Mac 17.05 ve altı için Docker

Ana makineye docker kapsayıcısından erişmek için ağ arabiriminize bir IP takma adı eklemeniz gerekir. İstediğiniz IP'yi bağlayabilirsiniz, sadece başka bir şey için kullanmadığınızdan emin olun.

sudo ifconfig lo0 alias 123.123.123.123/24

Ardından sunucunuzun yukarıda belirtilen IP'yi dinlediğinden emin olun 0.0.0.0. Localhost'ta dinliyorsa 127.0.0.1bağlantı kabul edilmez.

Ardından docker konteynerinizi bu IP'ye yönlendirin ve ana makineye erişebilirsiniz!

Test etmek curl -X GET 123.123.123.123:3000için kabın içinde gibi bir şey çalıştırabilirsiniz .

Takma ad her yeniden başlatma işleminde sıfırlanır, bu nedenle gerekirse bir başlatma komut dosyası oluşturun.

Çözüm ve daha fazla belge burada: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds


5
parlak ve teşekkürler, bu benim için konteyner içinde çalıştı. mysql -uroot -hdocker.for.mac.localhost
Richard Frank

1
docker.for.mac.localhost Tam da aradığım şeydi. Ama bu aynı zamanda cehennem kadar kirli. Docker'da, kanca docker.for.mac.localhost'un sadece Mac için değil, herhangi bir işletim sistemi için geçerli olacak genel bir docker dahili adı olmasını bekleyebilirsiniz. Ancak geliştirme amaçları için bu yeterince iyidir.
99Sono

Diyelim ki 9093 numaralı limana maruz kalan bir limana nasıl erişebilirim? Ulaşılamıyor ama docker.for.mac.localhost'a ping yaparsam, ulaşılabilir.Burada bir şey mi eksik?
Achilleus

1
Localhost alt alanlarının kullanımını yasaklayan bir RFC olduğundan, kapsayıcılardan ana bilgisayar çözünürlüğü için docker.for.mac.localhost (hala geçerli) yerine docker.for.mac.host.internal DNS adı kullanılmalıdır. Bkz. Tools.ietf.org/html/draft-west-let-localhost-be-localhost-06 .
Jya

Bu benim için işe yaramıyor. Ben docker run -e HOSTNAME= docker.for.mac.host.internal , kap oluşturulur ama hiçbir şey olmaz. Sonra crtl + C'ye ihtiyacım var. İle --net=host -e HOSTNAME=localhosten azından konteyner çalışır ve hizmet ı ihtiyacını bulamıyorum şikayet (MySQL db).
Jorge Orpinel

83

Yerel IP almak kapsayıcıdaki bir diğer ad (DNS) eşlemek için yukarıdaki yazı benzer bir kesmek yapıyorum. Ana sorun, hem Linux hem de OSX'te ana bilgisayar IP adresini çalıştıran basit bir komut dosyası ile dinamik olarak elde etmektir . Her iki ortamda da çalışan bu komut dosyasını ( "$LANG" != "en_*"yapılandırılmış Linux dağıtımında bile) yaptım :

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

Yani, Docker Compose kullanarak tam yapılandırma şu şekilde olacaktır:

Başlangıç ​​komut dosyası (docker-run.sh) :

export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)
docker-compose -f docker-compose.yml up

docker-compose.yml :

myapp:
  build: .
  ports:
    - "80:80"
  extra_hosts:
    - "dockerhost:$DOCKERHOST"

Ardından değiştirmek http://localhostiçin http://dockerhostkodunuzda.

DOCKERHOSTKomut dosyasının nasıl özelleştirileceğine dair daha ileri bir kılavuz için, nasıl çalıştığına dair bir açıklama ile bu gönderiye bir göz atın .


1
Kullanım durumunuza bağlı olarak, DOCKERHOSTdocker konteynerinizin yerel olarak bağlanması gereken herhangi bir hizmette "localhost" veya 0.0.0.0 yerine buradaki değeri kullanmaktan kurtulabilirsiniz .
enderland

2
: Biraz özel ağları ile uyumlu olacak şekilde çözümünüzü değiştirdiniz export DOCKERHOST=$(docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' <NETWORK-NAME> | awk -F "/" 'NR==1{print $1}') Nerede <AĞ-ADI> olabilir köprü veya ağın adı liman işçisi-oluşturmadeneyimine (genellikle tarafından tanımlanan yol-name - network_name ).
dieresys

1
Yorum eklemeniz gerekir: dockerhostdb bağlantısı için ana bilgisayar olarak kullanın (genellikle localhostyapılandırma dosyasında değiştirin ).
Justin

garip bir çözüm, ama bu php cli ile docker altında xdebug çalışması yapmak tek
Eddie

Acl, bu çözeltiden sonra haprokside çalışmayı bıraktı. Neden olduğu hakkında bir fikrin var mı?
HyukHyukBoi

41

Bu, uygulamanın sadece bağlanmayı beklediği herhangi bir koda veya ağa dokunmadan bir NGINX / PHP-FPM yığını üzerinde çalıştı localhost

mysqld.sockAna bilgisayardan kabın içine monte edin.

Mysql çalıştıran ana bilgisayarda mysql.sock dosyasının konumunu bulun:
netstat -ln | awk '/mysql(.*)?\.sock/ { print $9 }'

Bu dosyayı liman işçisinde beklendiği yere bağlayın:
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

2
Bu çok daha temiz bir çözümdür, Mysql'i dışarıya maruz bırakmaz (bir güvenlik duvarı kullanmıyorsa).
user1226868

5
Soketler TCP kadar ölçeklenmez, çünkü daha sık engellerler ve garip davranışlara neden olabilirler. Mümkün olduğunca TCP kullanın.
Joel E Salas

3
@JoelESalas Bu iddia için bir kaynağınız var mı?
Özel

Bunu en kolay çözüm olarak buldum. Thumbs up user833482! StackOverflow'a daha sık katkıda bulunmalısınız.
Özel

2
@JoelESalas Sanırım yanılıyorsunuz. Mysql istemci kütüphanesi, localhost'a bağlanmak yerine, localhost'a bağlanırken varsayılan olarak unix soketlerini bile kullanır. Bir unix soketi TCP yığınının ve yönlendirmesinin ek yükünü önler ve daha hızlı çalışmalıdır.
M Conrad

25

A kadar host.docker.internalHer platform için , konteynırımı herhangi bir manuel kurulum yapmadan NAT ağ geçidi olarak kullanabilirsiniz:

https://github.com/qoomon/docker-host


5
Bunun Windows kapsayıcısı olan Windows 19.03.2 için Docker'da çalışmadığını doğrulayabilirim.
KMC

bunu nasıl düzeltebilirim? (Ben bir windows kullanıcısı değilim)
qoomon

Ortamınız bağlantı noktası mysql'in kullanımını engellemiyorsa, barındırdığı bilgisayar adıyla sunucuya başvurabilirsiniz. Yani bağlantı dizenizde, bilgisayar adınızı sunucu adı olarak kullanın.
KMC

24

Linux için çözüm (çekirdek> = 3.6).

Tamam, localhost sunucunuzda 172.17.0.1 ip adresli varsayılan docker arayüzü docker0 var . Kapsayıcınız varsayılan ağ ayarlarıyla başladı --net = "bridge" .

  1. Docker0 arayüzü için route_localnet'i etkinleştirin:
    $ sysctl -w net.ipv4.conf.docker0.route_localnet=1
  2. Bu kuralları iptables'a ekleyin:
    $ iptables -t nat -I PREROUTING -i docker0 -d 172.17.0.1 -p tcp --dport 3306 -j DNAT --to 127.0.0.1:3306
    $ iptables -t filter -I INPUT -i docker0 -d 127.0.0.1 -p tcp --dport 3306 -j ACCEPT
  3. Localhost hariç herhangi birinden '%' erişimine sahip mysql kullanıcısı oluşturun:
    CREATE USER 'user'@'%' IDENTIFIED BY 'password';
  4. Komut dosyanızda mysql-server adresini 172.17.0.1 olarak değiştirin


Gönderen çekirdek belgelerinde :

route_localnet - BOOLEAN : Yönlendirme sırasında geri döngü adreslerini martian kaynağı veya hedefi olarak düşünmeyin. Bu, yerel yönlendirme amacıyla 127/8 kullanılmasını sağlar ( varsayılan YANLIŞ ).


1
İkinci iptable komutunun amacı nedir? İlki, 172.17.0.1:3306 ile 127.0.0.1:3306 ile eşleşen tüm tcp hedeflerini yeniden yazmak olduğunu anlayabiliyorum, ancak ikinci iptable komutu neden gerekli?
Patrick

17

Windows 10 için çözüm

Docker Topluluk Sürümü 17.06.0-ce-win18 2017-06-28 (kararlı)

docker.for.win.localhostDahili IP'ye çözümlemek için ana bilgisayarın DNS adını kullanabilirsiniz . (Bahsedilen bazı kaynakları uyarmak windowsancakwin )

Genel
benim koşuyordu localhost, benim Docker kaptan bağlantı olduğu benzer bir şey, yapmak için gerekli Azure Storage Emulatorve CosmosDB Emulator.

Azure Storage EmulatorVarsayılan dinler tarafından 127.0.0.1 , sen onun da varsayılan ayarları ile çalışacak bir çözüm arıyordu sınırın IP değiştirebilir iken.

Bu, Docker kapsayıcıdan SQL Serverve IISher ikisi de varsayılan bağlantı noktası ayarlarıyla ana bilgisayarımda yerel olarak çalışan bağlantı için de çalışır .


13

Çok basit ve hızlı, ana makine IP'nizi ifconfig (linux) veya ipconfig (windows) ile kontrol edin ve ardından bir

liman işçisi-compose.yml

version: '3' # specify docker-compose version

services:
  nginx:
    build: ./ # specify the directory of the Dockerfile
    ports:
      - "8080:80" # specify port mapping
    extra_hosts:
      - "dockerhost:<yourIP>"

Bu şekilde, kapsayıcınız ana makinenize erişebilir. DB'nize erişirken, daha önce belirttiğiniz adı, bu durumda "dockerhost" u ve ana bilgisayarınızın DB'nin çalıştığı bağlantı noktasını kullanmayı unutmayın.


HaProxy'de, bu çözüm bazı nedenlerden dolayı ACL'lerin çalışmasını durdurdu, sadece varsayılan ayar çalışıyor.
HyukHyukBoi

1
Linux sisteminde çalışan tek çözüm. +1
Rafik Farhad

11

Windows 10 Home'da Docker Toolbox kullanılırken yanıtların hiçbiri benim için işe yaramadı, ancak 10.0.2.2 , ana bilgisayarı bu adresteki VM'ye maruz bırakan VirtualBox kullandığından işe yaramadı.


2
İşe yarıyor. Hatta --network = host belirtmeye bile gerek yok. 10.0.2.2, ana bilgisayar için varsayılan IP olarak ayarlanmış gibi görünüyor. Teşekkürler.
TheManish

Ancak, bu statik IP'yi tüm Windows ve Mac sürümleri için kullanabilir miyim?, Komut dosyası aracılığıyla birden çok platform için nasıl işleyebilirim?
151291

Bu benim için çalıştı. Sadece ana makinenizde (windows) ipconfig'i çalıştırın ve IP adresini altına alınEthernet adapter vEthernet (DockerNAT)
Kihats

10

Windows'takiler için, köprü ağ sürücüsünü kullandığınızı varsayarsak, MySQL'i hyper-v ağ arayüzünün ip adresine özel olarak bağlamak isteyeceksiniz.

Bu, normalde gizli C: \ ProgramData \ MySQL klasörü altındaki yapılandırma dosyası aracılığıyla yapılır.

0.0.0.0'a bağlanma işe yaramaz. İhtiyaç duyulan adres docker yapılandırmasında da gösterilir ve benim durumumda 10.0.75.1 idi.


3
Bir madalyayı hak ediyorsun! Bunun için iki tam gündür çalışıyorum. Yardım ettiğin için teşekkürler!
Michael

1
Ben de iki tam gün çalışıyordum. Web'de bahsettiğim tek yer burası. Microsoft, bir Docker kapsayıcısından MSSQL'e bağlanma hakkında konuşurken tamamen sessizdir. Kendilerini hiç çalıştırıp çalışmadığını merak ediyor!
Contango

8

Edit: GitHub kavramı prototipleme sona erdi. Check out: https://github.com/sivabudh/system-in-a-box


İlk olarak, cevabım 2 gruba yönelik: Mac kullanan ve Linux kullananlara yönelik.

Ana bilgisayar ağı modu Mac'te çalışmıyor. Bir IP takma adı kullanmanız gerekir, bkz: https://stackoverflow.com/a/43541681/2713729

Ana bilgisayar ağı modu nedir? Bkz. Https://docs.docker.com/engine/reference/run/#/network-settings

İkincisi, Linux kullananlarınız için (doğrudan deneyimim Ubuntu 14.04 LTS ile oldu ve yakında üretimde 16.04 LTS'ye yükseltiyorum), evet , Docker kapsayıcısının içinde çalışan hizmetin üzerinde çalışan localhosthizmetlere bağlanmasını sağlayabilirsiniz. Docker ana bilgisayarı (örn. Dizüstü bilgisayarınız).

Nasıl?

Anahtar, Docker kapsayıcısını çalıştırdığınızda, ana bilgisayar moduyla çalıştırmanızdır . Komut şöyle görünür:

docker run --network="host" -id <Docker image ID>

Bir yaptığınızda ifconfig(eğer gerekecektir apt-get install net-toolsiçin konteyner ifconfigsizin konteynerin içinde çağrılabilir olması için), ağ arayüzleri Docker ana bilgisayarında biri (örn. Dizüstü) aynı olduğunu göreceksiniz.

Bir Mac kullanıcısı olduğumu belirtmek önemlidir, ancak Ubuntu'yu Parallels altında çalıştırıyorum, bu yüzden Mac kullanmak bir dezavantaj değil. ;-)

Ve NGINX kapsayıcısını bir localhost.


1
Ana bilgisayar modunun, OS ağ yığınını kullandığı için daha iyi performans sunduğuna dikkat etmek önemlidir .
sivabudh

2
Orada çok iyi bir nokta. Bir kaptan kullanılmayan IP eki bulunan bir ana bilgisayar hizmetine bağlanmak mümkün olmasına rağmen docs.docker.com/docker-for-mac/networking ekleyin . Hoş bir çözüm değil ... ama işe yarıyor.
Xavier Huppé

Burada iyi şeyler. Bir kez kabın içine bir kez --network="host"örneğin ana mysql bağlanmak için nasıl?
Michael

1
@Buccleuch Sadece kullanın localhost . GitHub kaynak koduma göz atın : github.com/sivabudh/system-in-a-box/blob/master/dj_host_docker/… . Ara 'HOST'Eğer Postgresql bağlanmak için 127.0.0.1 göreceksiniz.
sivabudh

@ User833482'ye göre birimi bağlayarak ve elbette docker kapsayıcısına mysql-client ve server kurduktan sonra ana bilgisayar mysql veritabanlarına erişebildim.
Michael

7

Mac OSX için en basit çözüm

Mac'inizin IP adresini kullanmanız yeterlidir. Mac'te IP adresini almak ve kapsayıcıdan kullanmak için bunu çalıştırın:

$ ifconfig | grep 'inet 192'| awk '{ print $2}'

Mac'inizde veya başka bir docker kapsayıcısında yerel olarak çalışan sunucu 0.0.0.0'ı dinlediği sürece, docker kapsayıcısı bu adresten ulaşabilir.

0.0.0.0'da dinleyen başka bir liman işçisi konteynerine erişmek istiyorsanız 172.17.0.1'i kullanabilirsiniz.


1
Mac için Docker docker.for.mac.host.internalşimdi ana makine adını gösterir.
Matt

5

Bu asıl sorunun cevabı değil. Benzer bir sorunu bu şekilde çözdüm. Çözüm tamamen şunlardan geliyor: Konteynerlerin İletişim Kurması için Docker Konteyner Ağını Tanımlama . Nic Raboy'a teşekkürler

Bir kapsayıcı ile diğeri arasında REST çağrıları yapmak isteyebilecek başkaları için bunu burada bırakarak. Soruyu cevaplar: docker ortamında localhost yerine ne kullanılır?

Ağınızın nasıl göründüğünü öğrenin docker network ls

Yeni bir ağ oluşturun docker network create -d my-net

İlk konteyneri başlat docker run -d -p 5000:5000 --network="my-net" --name "first_container" <MyImage1:v0.1>

İlk kapsayıcı için ağ ayarlarına göz atın docker inspect first_container. "Ağlar": "ağım" olmalıdır

İkinci kapsayıcıyı başlatın docker run -d -p 6000:6000 --network="my-net" --name "second_container" <MyImage2:v0.1>

İkinci kap için ağ ayarlarına bakın docker inspect second_container. "Ağlar": "ağım" olmalıdır

ssh ikinci konteynerinize docker exec -it second_container shveya docker exec -it second_container bash.

İkinci kabın içinde, ilk kaba ping atabilirsiniz ping first_container. Ayrıca, kod gibi çağrıları http://localhost:5000ile değiştirilebilirhttp://first_container:5000


Tam aradığım şey. Teşekkürler: D
Simar Singh

5

Pencereler için,

Bahar yapılandırmasında veritabanı url'sini değiştirdim: spring.datasource.url=jdbc:postgresql://host.docker.internal:5432/apidb

Sonra görüntüyü oluşturun ve çalıştırın. Benim için çalıştı.


ilginç ....
Phil

benim için çalışmıyor. Mac ve localhost mysql bağlanmak için bir php kapsayıcı çalışıyor. Herhangi bir fikir ?
A.Zalonis

4

Thomasleveil'ın cevabına katılmıyorum.

MySQL'in 172.17.42.1'e bağlanması, ana bilgisayardaki veritabanını kullanan diğer programların ona ulaşmasını önler. Bu, yalnızca tüm veritabanı kullanıcılarınız yerleştirilmişse çalışır.

MySQL'in 0.0.0.0'a bağlanması, db'yi dış dünyaya açacak, ki bu sadece yapmak için çok kötü bir şey değil, aynı zamanda yazarın orijinal sorularının aksine. "MySql, localhost üzerinde çalışıyor ve bir bağlantı noktasını dış dünyaya maruz bırakmıyor, bu yüzden localhost'a bağlı" diyor.

İvant'ın yorumuna cevap vermek

"Neden mysql'i docker0'a bağlamıyorsunuz?"

Bu mümkün değil. Mysql / mariadb belgeleri açıkça çeşitli arayüzlere bağlanmanın mümkün olmadığını söylüyor. Yalnızca 0, 1 veya tüm arabirimlere bağlayabilirsiniz.

Sonuç olarak, bir docker konteyner ana bilgisayardan (yalnızca localhost) veritabanına ulaşmak için herhangi bir yol bulmadım. Bu kesinlikle çok yaygın bir model gibi görünüyor, ama nasıl yapılacağını bilmiyorum.


4
docker ana bilgisayarından yine de 172.17.42.1adresi kullanarak MySQL sunucusuna bağlanabilirsiniz . Ama notun tam tersi. Aso, cevabımı hostMySQL sunucusunun bağlı kalmasına izin veren ağ moduyla düzenledim ve 127.0.0.1konteynırların ona bağlanmasına izin
verdim

hayır, dediğim gibi, mysql localhost'a bağlıysa 172.17.42.1'e bağlanamazsınız.
orzel

4
"Mysql'nin 172.17.42.1'e bağlanması, ana bilgisayardaki veritabanını kullanan diğer programların ona ulaşmasını engelleyecektir." - Bu doğru değil. Diğer programlar mysql kullanabilir, sadece localhost / 127.0.0.1 yerine 172.17.42.1'e bağlanmaları gerekir.
0x89

Bu yanıttaki sorunun çözümü genellikle MySQL sunucusuna bağlanıp 0.0.0.0db'nin internetten erişilememesi için bir güvenlik duvarı kurmaktır.
halfer

4

İşte benim çözümüm: benim durumum için çalışıyor

  • #bind-address = 127.0.0.1 /etc/mysql/mysql.conf.d adresinde yorum yaparak yerel mysql sunucusunu genel erişime ayarlayın

  • mysql sunucusunu yeniden başlat sudo /etc/init.d/mysql restart

  • herhangi bir ana bilgisayara kullanıcı kök erişimini açmak için aşağıdaki komutu çalıştırın mysql -uroot -proot GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION; FLUSH PRIVILEGES;

  • sh betiği oluştur: run_docker.sh

    #! Bin / bash

    HOSTIP = `ip -4 addr kapsamı göster global dev eth0 | grep inet | awk '{print \ $ 2}' | kes -d / -f 1`


      docker run -it -d - adı web-uygulaması \
                  --add-host = yerel: $ {HOSTIP} \
                  -p 8080: 8080 \
                  -e DATABASE_HOST = $ {HOSTIP} \
                  -e DATABASE_PORT = 3306 \
                  -e DATABASE_NAME = demo \
                  -e DATABASE_USER = kök \
                  -e DATABASE_PASSWORD = kök \
                  sopheamak / springboot_docker_mysql

  
  • docker-besteci ile çalıştır

    sürüm: '2.1'

    Hizmetler:
    tomcatwar: extra_hosts: - "yerel: 10.1.2.232" görüntü: sopheamak / springboot_docker_mysql
    portlar: - 8080: 8080 çevre: - DATABASE_HOST = yerel - DATABASE_USER = kök - DATABASE_PASSWORD = kök - DATABASE_NAME = demo - DATABASE_PORT = 3306


4

Birkaç çözüm akla geliyor:

  1. Bağımlılıklarınızı önce kaplara taşıyın
  2. Diğer hizmetlerinizi harici olarak erişilebilir hale getirin ve bu harici IP ile bunlara bağlanın
  3. Kapsayıcılarınızı ağ yalıtımı olmadan çalıştırın
  4. Ağ üzerinden bağlanmaktan kaçının, bunun yerine birim olarak monte edilmiş bir soket kullanın

Bunun kutudan çıkmamasının nedeni, kapsayıcıların varsayılan olarak kendi ağ ad alanlarıyla çalışmasıdır. Bu, localhost (veya geri döngü arayüzüne işaret eden 127.0.0.1) kap başına benzersiz olduğu anlamına gelir. Buna bağlanmak, docker'ın dışında veya farklı bir docker konteynerinin içinde çalışan servislere değil konteynerin kendisine bağlanır.

Seçenek 1 : Bağımlılığınız bir kaba taşınabiliyorsa, önce bunu yapardım. Diğerleri kabınızı kendi ortamlarında çalıştırmaya çalışırken uygulama yığınınızı taşınabilir hale getirir. Ayrıca, bağlantı noktasını, barındırılmamış diğer hizmetlerin yine de erişebileceği ana makinenizde yayınlayabilirsiniz. Bağlantı noktasını -p 127.0.0.1:3306:3306, yayınlanan bağlantı noktası gibi sözdizimiyle harici olarak erişilebilir olmasını önlemek için bağlantı noktası ana makinenizdeki localhost arabiriminde de yayınlayabilirsiniz.

Seçenek 2 : Ana bilgisayarın IP adresini kabın içinden algılamanın çeşitli yolları vardır, ancak her birinin çalıştıkları yerde sınırlı sayıda senaryo vardır (örn. Mac için Docker gerektirir). En taşınabilir seçenek, ana makine IP'nizi bir ortam değişkeni veya yapılandırma dosyası gibi bir şeyle kaba enjekte etmektir, örneğin:

docker run --rm -e "HOST_IP=$(ip r s 0/0 | awk '{print $3}')" ...

Bu, hizmetinizin bir güvenlik sorunu olabilecek harici arayüzü dinlemesini gerektirir. Ana bilgisayarın IP adresini kapsayıcıdan almanın diğer yöntemleri için bu gönderiye bakın .

Seçenek 3 : Ağ yalıtımı olmadan çalıştırma, yani ile çalıştırma --net host, uygulamanızın ana bilgisayar ağ ad alanında çalıştığı anlamına gelir. Bu, kapsayıcı için daha az yalıtımdır ve DNS ile paylaşılan bir docker ağı üzerinden diğer kapsayıcılara erişemeyeceğiniz anlamına gelir (bunun yerine, diğer kapsayıcı uygulamalara erişmek için yayımlanmış bağlantı noktalarını kullanmanız gerekir). Ancak, ana bilgisayarda yalnızca ana bilgisayarda dinlenen diğer hizmetlere erişmesi gereken uygulamalar 127.0.0.1için bu en kolay seçenek olabilir.

Seçenek 4 : Çeşitli servisler ayrıca dosya sistemi tabanlı bir soket üzerinden erişime izin verir. Bu soket, ağa bağlanmadan ana makine hizmetine erişmenizi sağlayan, bağlanmış bir birim olarak kaba monte edilebilir. Liman işçisi motoruna erişim için, genellikle /var/run/docker.sockkonteynere montaj örnekleri görürsünüz (konteynır köküne ana bilgisayara erişim verir). Mysql ile, mysql'in soketi kullanarak dönüştürdüğü gibi bir şey deneyebilir -v /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysql.sockve bağlanabilirsiniz localhost.


3

Alp görüntüsünü kullanarak ana bilgisayar ipini alabilirsiniz

docker run --rm alpine ip route | awk 'NR==1 {print $3}'

Komutu çalıştırmak için her zaman alpin kullandığınız için bu daha tutarlı olacaktır.

Mariano'nun cevabına benzer şekilde, bir ortam değişkeni ayarlamak için aynı komutu kullanabilirsiniz

DOCKER_HOST=$(docker run --rm alpine ip route | awk 'NR==1 {print $3}') docker-compose up

3

Localhost hizmetinin bağlandığı arayüzü değiştiremediğiniz Linux için

Çözmemiz gereken iki sorun var

  1. Ana bilgisayarın IP'sini alma
  2. Localhost servisimizi Docker için kullanılabilir hale getirme

İlk sorun, qoomon'un docker-host görüntüsü kullanılarak çözülebilir diğer cevapların verdiği gibi .

Bu kapsayıcıya erişebilmeniz için diğer kapınızla aynı köprü ağına eklemeniz gerekir. Kabınızın içinde bir terminal açın ve ping atabildiğinizden emin olun dockerhost.

bash-5.0# ping dockerhost
PING dockerhost (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.523 ms

Şimdi, daha zor sorun, hizmet liman işçisi için erişilebilir hale getirmek.

Ana bilgisayardaki bir bağlantı noktasına erişip erişemeyeceğimizi kontrol etmek için telnet kullanabiliriz (bunu yüklemeniz gerekebilir).

Sorun şu ki, kabımız yalnızca SSH gibi tüm arabirimlere bağlanan hizmetlere erişebilecektir:

bash-5.0# telnet dockerhost 22
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

Ancak yalnızca localhost'a bağlı hizmetlere erişilemez:

bash-5.0# telnet dockerhost 1025
telnet: can't connect to remote host (172.20.0.2): Connection refused

Buradaki uygun çözüm, hizmeti liman işçileri köprü ağına bağlamak olacaktır. Ancak bu cevap, bunu değiştirmenizin mümkün olmadığını varsayar. Bunun yerine kullanacağız iptables.

İlk olarak, liman işçisinin kullandığı köprü ağının adını bulmamız gerekir ifconfig. Adsız bir köprü kullanıyorsanız, bu sadece olacaktır docker0. Ancak, adlandırılmış bir ağ br-kullanıyorsanız, bunun yerine docker ile başlayan bir köprünüz olacaktır. Benim br-5cd80298d6f4.

Bu köprünün adını aldığımızda, bu köprüden localhost'a yönlendirmeye izin vermeliyiz. Bu, güvenlik nedeniyle varsayılan olarak devre dışıdır:

sysctl -w net.ipv4.conf.<bridge_name>.route_localnet=1

Şimdi iptableskuralımızı belirleyelim. Konteynerimiz yalnızca liman köprüsü ağındaki bağlantı noktalarına erişebildiğinden, hizmetimizin aslında bu ağdaki bir bağlantı noktasına bağlı olduğunu iddia edeceğiz.

Bunu yapmak için tüm istekleri adresine <docker_bridge>:portyönlendireceğizlocalhost:port

iptables -t nat -A PREROUTING -p tcp -i <docker_bridge_name> --dport <service_port> -j DNAT --to-destination 127.0.0.1:<service_port>

Örneğin, bağlantı noktası 1025'teki hizmetim için

iptables -t nat -A PREROUTING -p tcp -i br-5cd80298d6f4 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025

Artık hizmetinize konteynerden erişebilmeniz gerekir:

bash-5.0# telnet dockerhost 1025
220 127.0.0.1 ESMTP Service Ready

1
Bu, @ ray-d'nin yukarıda bahsettiği ile aynıdır, ancak güzel açıklanmıştır. Teşekkür ederim! Ayrıca, docker-compose kullanırken, docker0 arabirimine gelen tüm paketler için PREROUTING zincirine de bir DNAT kuralı eklemem gerekiyordu: çünkü, docker-compose derlemeler sırasında docker0 kullanıyor gibi görünüyor (çalıştırma sırasında değil, şaşırtıcı bir şekilde): sysctl -w net.ipv4.conf.docker0.route_localnet=1veiptables -t nat -A PREROUTING -p tcp -i docker0 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025
arvindd

3

Geçidi bilmeniz gerekiyor ! Yerel sunucu ile benim çözüm altında maruz 0.0.0.0:8000, sonra alt ağ ile docker çalıştırmak ve konteyner gibi çalıştırmak oldu :

docker network create --subnet=172.35.0.0/16 --gateway 172.35.0.1 SUBNET35
docker run -d -p 4444:4444 --net SUBNET35 <container-you-want-run-place-here>

Böylece, geri dönme işleminize artık http://172.35.0.1:8000


3

Bunu dene:

version: '3.5'
services:
  yourservice-here:
    container_name: container_name
    ports:
      - "4000:4000"
    extra_hosts: # <---- here
      - localhost:192.168.1.202
      - or-vitualhost.local:192.168.1.202

Almak 192.168.1.202, kullanırifconfig

Bu benim için çalıştı. Umarım bu yardım!


2

CGroups ve Namespace'ler Konteyner Ekosisteminde büyük rol oynamaktadır.

Ad alanı bir yalıtım katmanı sağlar. Her kapsayıcı ayrı bir ad alanında çalışır ve erişimi bu ad alanı ile sınırlıdır. Cgroups her kabın kaynak kullanımını kontrol ederken, Namespace bir sürecin ilgili kaynağa ne görebileceğini ve erişebileceğini kontrol eder.

İşte takip edebileceğiniz çözüm yaklaşımının temel anlayışı,

Ağ Ad Alanını Kullan

Bir kap görüntünün dışına çıktığında, bir ağ arayüzü tanımlanır ve oluşturulur. Bu, kaba benzersiz IP adresi ve arayüzü verir.

$ docker run -it alpine ifconfig

Ad alanını ana bilgisayar olarak değiştirerek, cotainers ağları arabiriminde yalıtılmış kalmaz, işlem ana makinelerin ağ arabirimine erişebilir.

$ docker run -it --net=host alpine ifconfig

İşlem bağlantı noktalarını dinlerse, ana bilgisayar arabiriminde dinlenir ve kapsayıcıya eşlenir.

PID Ad Alanını Kullanma Pid ad alanını değiştirerek, bir kabın normal kapsamı dışındaki diğer işlemlerle etkileşime girmesini sağlar.

Bu kapsayıcı kendi ad alanında çalışacaktır.

$ docker run -it alpine ps aux

Ana bilgisayar için ad alanını değiştirerek, konteyner sistem üzerinde çalışan diğer tüm işlemleri de görebilir.

$ docker run -it --pid=host alpine ps aux

Ad Alanını Paylaşma

Bu, üretimde bunu yapmak için kötü bir uygulamadır, çünkü güvenlik açıklarına neden olabilecek kapsayıcı güvenlik modelinden çıkıyorsunuz ve kulak misafiri için kolay erişim elde ediyorsunuz. Bu, yalnızca araçlarda hata ayıklama ve kapsayıcı güvenliğinde boşlukların anlaşılması içindir.

İlk kapsayıcı nginx sunucusudur. Bu, yeni bir ağ oluşturur ve ad alanını işler. Bu kapsayıcı, yeni oluşturulan ağ arabiriminin 80 numaralı bağlantı noktasına bağlanacaktır.

$ docker run -d --name http nginx:alpine

Başka bir kapsayıcı artık bu ad alanını yeniden kullanabilir,

$ docker run --net=container:http mohan08p/curl curl -s localhost

Ayrıca, bu kap, paylaşılan bir kapsayıcıdaki işlemlerle arabirimi görebilir.

$ docker run --pid=container:http alpine ps aux

Bu, uygulamayı değiştirmeden veya yeniden başlatmadan kapsayıcılara daha fazla ayrıcalık vermenizi sağlar. Benzer şekilde, ana bilgisayarda mysql'e bağlanabilir, uygulamanızı çalıştırabilir ve hata ayıklayabilirsiniz. Ancak, bu şekilde gitmek tavsiye edilmez. Umarım yardımcı olur.


1

Windows Machine için: -

Yükleme işlemi sırasında liman bağlantı noktasını rasgele göstermek için aşağıdaki komutu çalıştırın

$docker run -d --name MyWebServer -P mediawiki

resim açıklamasını buraya girin

resim açıklamasını buraya girin

Yukarıdaki kapsayıcı listesinde 32768 olarak atanan bağlantı noktasını görebilirsiniz.

localhost:32768 

Mediawiki sayfasını görebilirsiniz


5
Bu yanıt bazı kullanıcılara faydalı bilgiler sunsa da , yanlış bir yol var ! Bu, ana makineden kapta çalışan bir hizmete erişmekle ilgilidir . Ancak soru, ana bilgisayarda çalışan bir hizmete kapsayıcıdan erişmekle ilgiliydi .
einjohn


1

Ben kabın ip için MySQL bir kullanıcı oluşturarak çözdü:

$ sudo mysql<br>
mysql> create user 'username'@'172.17.0.2' identified by 'password';<br>
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on database_name.* to 'username'@'172.17.0.2' with grant option;<br>
Query OK, 0 rows affected (0.00 sec)

$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
<br>bind-address        = 172.17.0.1

$ sudo systemctl restart mysql.service

Sonra konteyner üzerinde: jdbc:mysql://<b>172.17.0.1</b>:3306/database_name


Bu en basit çözüm. Benim için çalıştı ve ben çok sevk
Sopia Alfred

-1

Bunu yapmanın yolu, ana değişken IP'yi ortam değişkeni olarak konteynere geçirmektir. Kapsayıcı daha sonra bu değişken tarafından ana bilgisayara erişin.


Bunu nasıl yaptığınızı gösterebilir misiniz? Bu yaklaşımı denemiştim ama pek bir başarı bulamadım
Şubat'ta

`docker run -i -t -e HOST = 10.145.2.123 ubuntu kökü @ ce2a843da3ee: / tmp # ./telnet $ HOST 22 Deniyor 10.145.2.123 ... 10.145.2.123'e bağlı. Kaçış karakteri '^]'. SSH-2.0-OpenSSH_7.4`
F. Kam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.