Docker kapsayıcısından ana makine bağlantı noktasına nasıl erişilir


278

Jenkinleri çalıştıran bir liman işçisi konteynırım var. Oluşturma işleminin bir parçası olarak, ana bilgisayarda yerel olarak çalışan bir web sunucusuna erişmem gerekiyor. Ana bilgisayar web sunucusunun (bir bağlantı noktasında çalışacak şekilde yapılandırılabilen) jenkins kapsayıcısına maruz kalmasının bir yolu var mı?

EDIT: Docker doğal olarak bir Linux makinesinde çalıştırıyorum.

GÜNCELLEME:

Aşağıdaki @larsks yanıtına ek olarak, ana bilgisayar IP'sinin IP adresini ana makineden almak için aşağıdakileri yaparım:

ip addr show docker0 | grep -Po 'inet \K[\d.]+'

Bu korkunç bir cevap olduğu için bir yorum kullanmak, ancak genellikle bir boot2docker kurulumu olmadığı sürece genellikle 172.17.1.78 adresinden erişebileceğinize inanıyorum.
CashIsClay

@CashIsClay Bunu denedim ve hala bu hatayı aldımcurl: (7) Failed to connect to 172.17.1.78 port 7000: No route to host
Tri Nguyen

Siz belirtmediniz; boot2docker çalıştırıyor musunuz yoksa Linux'ta Docker'ı yerel olarak mı çalıştırıyorsunuz?
larsks

@larsks üzgünüm, soruyu yeni güncelledim - Linux'ta doğal olarak çalıştırıyorum.
Tri Nguyen

Yanıtlar:


206

Docker'ı Linux'ta yerel olarak çalıştırırken, sunucu hizmetlerinin IP adresini kullanarak ana bilgisayar hizmetlerine erişebilirsiniz. docker0 arayüzün . Konteynerin içinden, bu varsayılan rotanız olacaktır.

Örneğin, sistemimde:

$ ip addr show docker0
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::f4d2:49ff:fedd:28a0/64 scope link 
       valid_lft forever preferred_lft forever

Ve bir kabın içinde:

# ip route show
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0  src 172.17.0.4 

Bu IP adresini basit bir kabuk komut dosyası kullanarak ayıklamak oldukça kolaydır:

#!/bin/sh

hostip=$(ip route show | awk '/default/ {print $3}')
echo $hostip

iptablesDocker kapsayıcılarından bağlantılara izin vermek için ana makinenizdeki kuralları değiştirmeniz gerekebilir . Böyle bir şey işinizi görecektir:

# iptables -A INPUT -i docker0 -j ACCEPT

Bu, ana bilgisayardaki bağlantı noktalarına Docker kapsayıcılarından erişime izin verir. Bunu not et:

  • iptables kuralları sipariş edilir ve bu kural diğer kuralların kendisinden önce gelmesine bağlı olarak doğru olanı yapabilir veya yapmayabilir.

  • yalnızca (a) üzerinde dinleme INADDR_ANY(0.0.0.0 olarak da bilinir) veya docker0arabirimi açıkça dinleyen ana bilgisayar hizmetlerine erişebileceksiniz .


1
Teşekkürler. IP adresini almak, iptables'ı değiştirmeden benim için gerekli olan tek şeydi :)
Tri Nguyen

2
İlgili Bağlantı: Kapsayıcı / etc /
hosts'e

7
MAC için Docker ne dersiniz? AFAIK "MAC için Docker" için avilable docker0 ağı yok. Bu durumda ana makineye kapsayıcıdan nasıl bağlanabilirim?
Vijay

17
MAC v 17.06 veya üstü için Docker kullanıyorsanız docker.for.mac.localhost, localhostveya yerine kullanın 127.0.0.1. İşte doc .
merito

1
IP adresini almak yerine ana bilgisayarımın ana bilgisayar adını kullandım (ana bilgisayardaki ana bilgisayar adı komutu)
Marek F

312

MacOS ve Windows için

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

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

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.11.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

Sonra sunucunuzun yukarıda belirtilen IP'yi dinlediğinden emin olun 0.0.0.0. Localhost üzerinden 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


Bunu başarıyla test ettim. Güvenlik duvarını kapatmaya gerek yok
alvaro g

15
Haziran 2017'de piyasaya sürülen 17.06'dan itibaren, önerileri, docker.for.mac.localhostana bilgisayar tarafından kullanılan dahili IP adresine çözülecek olan yalnızca Mac için özel DNS adına bağlanmaktır ! ... test ettim ve gerçekten işe yarıyor! :)
Kyr

Benim gibi Mac kullanıcıları için yanıtta dikkat edin. Teşekkürler. Ama alamadım bir şey neden ip route show | awk '/default/ {print $3}'bir IP ve docker.for.mac.localhostdiğeri vermek olduğunu.
dmmd

8
olarak değiştirildi host.docker.internal docs.docker.com/docker-for-mac/networking/…
Snowball

1
Kullanımını tavsiye host.docker.internalliman işçisi kap hem de yapılandırma 127.0.0.1 host.docker.internaliçinde barındıran dosyanın.
junlin

85

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


15
Kapsayıcıların sanallaştırılmış ortamlarda çalışması nedeniyle Dpcker for Windows / Docker for Mac kullanan kişiler için çalışmayacak: Hyper-V (Windows) / xhyve (Mac)
ninjaboy

6
BU! İşte cevap!
user3751385

15
Sadece kayıt için: Docker Componse içinde, network_mode: "host"
jbarros

Bu benim için istemci ve sunucuda Mac için Docker 19.03.1 sürümünde çalışmıyor. Keşke çalışsaydı, ama olmadı.
kil

1
Mac'te olsam bile, iki liman işçisi konteyneri arasındaki iletişimi istediğinizde çalışır ve tüm uygulamayı liman işçisi imajına dönüştürdüğümde benim için yeterlidir
bormat

27

Docker-compose ile çözüm: Ana bilgisayar tabanlı hizmete erişmek için https://docs.docker.com/compose/compose-file/#network_modenetwork_mode parametresini kullanabilirsiniz

version: '3'
services:
  jenkins:
    network_mode: host

EDIT 2020-04-27: yalnızca yerel geliştirme ortamında kullanılması önerilir.


O zaman cenkins'e nasıl erişilir? Ana bilgisayar ağ modunu kullanırsanız bağlantı noktası yönlendirme çalışmıyor gibi görünüyor
Jeff Tian

1
çok riskli bir çözümdür ve hiç tavsiye edilmez. açıkça gerekmedikçe ana bilgisayar ağımızı konteynerlere açmamalıyız
Fatemeh Majd


12

Https://github.com/qoomon/docker-host tam olarak yapmak için bir liman işçisi konteyneri oluşturdum

Daha sonra ana bilgisayar sistemine erişmek için kapsayıcı adı dns'i kullanabilirsiniz. curl http://dockerhost:9200


Bu akıllıca bir çözüm. Bunu çok fazla trafikle kullanan herhangi bir şeyin farkında mısınız? Bu kapsayıcı üzerinden tüm trafiği proxy yapmak için ek yük olabilir.
bcoughlan

3
Evet, sadece geri
tepme

11

Tüm bu ağ önemsizlerine daha basit bir çözümün, hizmet için etki alanı soketini kullanmak olduğunu bulduk. Yine de ana bilgisayara bağlanmaya çalışıyorsanız, soketi bir birim olarak takmanız yeterlidir ve yolunuza devam edersiniz. Postgresql için bu kadar basitti:

docker run -v /var/run/postgresql:/var/run/postgresql

Daha sonra sadece ağ yerine soketi kullanmak için veritabanı bağlantımızı kurduk. Kelimenin tam anlamıyla bu kadar kolay.


Bu harika bir çözüm. İyi iş!
ücretli bir inek

2
Bilginize, bununla büyük bir sorunla karşılaştık: Mac için Docker, takılı birimler olarak yuvaları desteklemiyor. Bu, bir Mac kişi denemeden yüzmeye gitti. :(
mlissner

Teşekkürler! Linux'ta bir cazibe gibi çalıştı!
Marcelo Cardoso

7

Çeşitli çözümü araştırdım ve bunu en az hacky çözüm buluyorum:

  1. Köprü ağ geçidi IP'si için statik bir IP adresi tanımlayın.
  2. Ağ geçidi IP'sini extra_hostsyönergeye ek bir giriş olarak ekleyin .

Tek dezavantajı, bunu yapan birden fazla ağınız veya projeniz varsa, IP adresi aralıklarının çakışmadığından emin olmanız gerekir.

İşte bir Docker Compose örneği:

version: '2.3'

services:
  redis:
    image: "redis"
    extra_hosts:
      - "dockerhost:172.20.0.1"

networks:
  default:
    ipam:
      driver: default
      config:
      - subnet: 172.20.0.0/16
        gateway: 172.20.0.1

Daha sonra "dockerhost" ana bilgisayar adını kullanarak ana bilgisayardaki bağlantı noktalarına kabın içinden erişebilirsiniz.



3

Ana makinenizde çalışan yerel web sunucusuna iki şekilde erişebilirsiniz.

  1. Genel IP ile Yaklaşım 1

    Jenkins docker kapsayıcısındaki web sunucusuna erişmek için ana makine genel IP adresini kullanın.

  2. Ana bilgisayar ağı ile yaklaşım 2

    Ana makinenin ağ yığınına Jenkins docker kapsayıcısını eklemek için "--net host" kullanın. Ana bilgisayar yığınına dağıtılan kapsayıcıların ana bilgisayar arabirimine tam erişimi vardır. Ana web sitesinin özel bir IP adresiyle docker kapsayıcısındaki yerel web sunucusuna erişebilirsiniz.

NETWORK ID          NAME                      DRIVER              SCOPE
b3554ea51ca3        bridge                    bridge              local
2f0d6d6fdd88        host                      host                local
b9c2a4bc23b2        none                      null                local

Ana bilgisayar ağıyla bir kapsayıcı başlatın ve docker kapsayıcısından erişilebilen tüm kullanılabilir ağ IP adreslerini listelemek için Eg: docker run --net host -it ubuntuçalıştırın ifconfig.

Örneğin: Yerel ana bilgisayarımda bir nginx sunucusu başlattım ve Ubuntu docker konteynerinden nginx web sitesi URL'lerine erişebiliyorum.

docker run --net host -it ubuntu

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
a604f7af5e36        ubuntu              "/bin/bash"         22 seconds ago      Up 20 seconds                           ubuntu_server

Özel ağ IP adresine sahip Ubuntu docker kapsayıcısından Nginx web sunucusuna (yerel ana makinede çalışıyor) erişme.

root@linuxkit-025000000001:/# curl 192.168.x.x -I
HTTP/1.1 200 OK
Server: nginx/1.15.10
Date: Tue, 09 Apr 2019 05:12:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Mar 2019 14:04:38 GMT
Connection: keep-alive
ETag: "5c9a3176-264"
Accept-Ranges: bytes

3

İçin docker-composekonteynerler arasında kullanan kabul çözümü özel bir ağ oluşturmak için köprü ağ kullanarak docker0yapar değil iş kaplardan çıkış arayüzü olmadığı için docker0ama bunun yerine rasgele oluşturulmuş bir arayüz kimliği gibi açıklanmıştır:

$ ifconfig

br-02d7f5ba5a51: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.32.1  netmask 255.255.240.0  broadcast 192.168.47.255

Ne yazık ki, rasgele id öngörülebilir değildir ve oluşturma ağını yeniden oluşturmak zorunda kaldığında değişecektir (örneğin bir ana bilgisayar yeniden başlatıldığında). Benim çözümüm, bilinen bir alt ağda özel ağ oluşturmak ve iptablesbu aralığı kabul edecek şekilde yapılandırmaktır :

Dosya snippet'ini oluştur:

version: "3.7"

services:
  mongodb:
    image: mongo:4.2.2
    networks:
    - mynet
    # rest of service config and other services removed for clarity

networks:
  mynet:
    name: mynet
    ipam:
      driver: default
      config:
      - subnet: "192.168.32.0/20"

Ortamınız gerektiriyorsa alt ağı değiştirebilirsiniz. Tuşlarını 192.168.32.0/20kullanarak keyfi olarak seçtimdocker network inspectVarsayılan olarak nelerin yaratıldığını görmek için .

iptablesAna bilgisayarda kaynak olarak özel alt ağa izin verecek şekilde yapılandırın :

$ iptables -I INPUT 1 -s 192.168.32.0/20 -j ACCEPT

Bu mümkün olan en basit iptableskuraldır. Hedef kısıtlama gibi başka kısıtlamalar da ekleyebilirsiniz. Çalıştığınız için mutlu olduğunuzda iptables kurallarınızı devam ettirmeyi unutmayın.

Bu yaklaşım, tekrarlanabilir ve dolayısıyla otomatikleştirilebilir olma avantajına sahiptir. Oluşturma dosyamı templatedeğişken değiştirme ile dağıtmak için ansible'ın modülünü kullandım ve ardından sırasıyla güvenlik duvarı kurallarını yapılandırmak ve sürdürmek için iptablesve shellmodüllerini kullanıyorum .


Bunu öneren birden fazla cevap gördüm iptables -A INPUT -i docker0 -j ACCEPT, ancak bu bana yardımcı olmadı, ancak iptables -I INPUT 1 -s 192.168.32.0/20 -j ACCEPTburada önerilenler sorunumu çözdü.
Terry Brown

1

Bu eski bir soru ve birçok cevabı vardı, ama bunların hiçbiri bağlamıma yeterince uymuyor. Benim durumumda, kaplar çok yalın ve ana bilgisayarın ip adresini kaptan çıkarmak için gerekli ağ araçlarını içermiyor.

Ayrıca, --net="host" yaklaşımın kullanılması, birkaç kap ile iyi yalıtılmış ağ yapılandırmasına sahip olmak istediğinde uygulanamayan çok kaba bir yaklaşımdır.

Benim yaklaşımım, ana bilgisayarın adresini ana bilgisayarın tarafında ayıklamak ve sonra --add-hostparametreyle kaba iletmektir:

$ docker run --add-host=docker-host:`ip addr show docker0 | grep -Po 'inet \K[\d.]+'` image_name

veya ana bilgisayarın IP adresini bir ortam değişkenine kaydedin ve daha sonra bu değişkeni kullanın:

$ DOCKERIP=`ip addr show docker0 | grep -Po 'inet \K[\d.]+'`
$ docker run --add-host=docker-host:$DOCKERIP image_name

Ardından, docker-hostkabın hosts dosyasına eklenir ve bunu veritabanı bağlantı dizelerinizde veya API URL'lerinizde kullanabilirsiniz.


0

"Zaten" oluşturulan iki liman işçisi resminiz varsa ve birbirleriyle iletişim kurmak için iki kap koymak istediğinizde.

Bunun için, her kapsayıcıyı kendi --adıyla rahatça çalıştırabilir ve aralarındaki iletişimi sağlamak için --link bayrağını kullanabilirsiniz. Ancak docker derlemesi sırasında bunu alamazsınız.

Benim gibi bir senaryodayken,

docker build -t "centos7/someApp" someApp/ 

Denediğinde kırılıyor

curl http://172.17.0.1:localPort/fileIWouldLikeToDownload.tar.gz > dump.tar.gz

ve "kıvırmak / wget" takılı kalmayacaksınız.

Bunun nedeni, liman işçisi tarafından varsayılan olarak bir kapsayıcıdan ana makineye veya ana makinenizde çalışan diğer kapsayıcılara iletişimi yasaklayan güvenliktir. Bu benim için oldukça şaşırtıcıydı, söylemeliyim ki, yerel bir makinede çalışan docker makinelerinin ekosisteminin kusursuzca birbirine çok fazla engel olmadan erişebileceğini beklersiniz.

Bunun açıklaması aşağıdaki belgelerde ayrıntılı olarak açıklanmaktadır.

http://www.dedoimedo.com/computers/docker-networking.html

Ağ güvenliğini düşürerek hareket etmenize yardımcı olan iki hızlı geçici çözüm verilmiştir.

En basit alternatif sadece güvenlik duvarını kapatmak veya herkese izin vermektir. Bu, systemctl stop firewalld, iptables -F veya eşdeğeri olabilecek gerekli komutu çalıştırmak anlamına gelir.

Umarım bu bilgi işine yarar.


3
Tıpkı bir not olarak, --linkartık kullanımdan kaldırıldı
Mr.Budris

0

Benim için (Windows 10, Docker Engine v19.03.8), https://stackoverflow.com/a/43541732/7924573 ve https://stackoverflow.com/a/50866007/7924573'ün bir karışımıydı .

  1. anasistem / ip'i anasistem.docker.internal olarak değiştirin,
    örneğin: LOGGER_URL = " http: //host.docker.internal: 8085 / log "
  2. network_mode'u köprüye ayarlayın (bağlantı noktası iletmeyi korumak istiyorsanız; ana bilgisayar kullanmıyorsanız ):
    version: '3.7' services: server: build: . ports: - "5000:5000" network_mode: bridge veya alternatif olarak: --net="bridge"docker-compose ( https://stackoverflow.com/a/48806927/7924573 )
    Önceki cevaplarda belirtildiği gibi: Bu sadece yerel bir geliştirme ortamında kullanılmalıdır .
    Daha fazla bilgi için: https://docs.docker.com/compose/compose-file/#network_mode ve https://docs.docker.com/docker-for-windows/networking/#use-cases-and-workarounds
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.