Cara berkomunikasi antara kontainer Docker melalui "nama host"

91

Saya berencana untuk membagi server monolitik saya menjadi banyak kontainer buruh pelabuhan kecil tetapi belum menemukan solusi yang baik untuk "komunikasi antar kontainer". Ini adalah skenario target saya:

Skenario target

Saya tahu bagaimana menghubungkan kontainer dan bagaimana mengekspos port, tetapi tidak ada solusi yang memuaskan bagi saya.

Apakah ada solusi untuk berkomunikasi melalui nama host (nama wadah) antara wadah seperti di jaringan server tradisional?

Patrick Gotthard
sumber
Saya telah menulis sebuah dokumen baru-baru ini dengan melakukan apa yang Anda cari. Ini pada dasarnya mendokumentasikan cara memasang banyak wadah (satu per proses) dan membuatnya terintegrasi. "komunikasi antar-kontainer" adalah bagian dari permainan .
xuhdev
Saya baru saja menemukan Tumtum Blog dan menemukan paragraf ini di dokumentasi resmi Docker . Saya tidak tahu apakah saya telah melewatkan paragraf ini sepanjang waktu atau apakah itu baru ditambahkan tetapi seharusnya itulah yang saya butuhkan :)
Patrick Gotthard
buruh pelabuhan 1,10 keluar, dan koneksi buruh pelabuhan mengagumkan ( github.com/docker/docker/blob/… ). Lihat jawaban saya yang diedit di bawah
VonC
2
Saya pikir Anda harus mencoba docker-compose . Bekerja dengan sangat baik.
Suhas Chikkanna

Jawaban:

27

Sunting: Setelah Docker 1.9, docker networkperintah (lihat di bawah https://stackoverflow.com/a/35184695/977939 ) adalah cara yang disarankan untuk mencapai ini.


Solusi saya adalah menyiapkan dnsmasq pada host agar catatan DNS diperbarui secara otomatis: Catatan "A" memiliki nama wadah dan mengarah ke alamat IP wadah secara otomatis (setiap 10 detik). The Script update otomatis yang disisipkan di sini:

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done

Pastikan layanan dnsmasq Anda tersedia di docker0. Kemudian, mulai penampung Anda dengan --dns HOST_ADDRESSmenggunakan layanan mini dns ini.

Referensi: http://docs.blowb.org/setup-host/dnsmasq.html

xuhdev
sumber
Itu terlihat menarik, jauh lebih tangguh daripada jawaban --link saya. +1
VonC
@VonC sepertinya libnetwork baru dapat menggantikan solusi ini. Mari kita lihat.
xuhdev
@xuhdev Saya menyiapkan dnsmasq seperti di docs.blowb.org/setup-host/dnsmasq.html . Tetapi saya menghadapi masalah saat menggunakan penggalian dari kontainer buruh pelabuhan, waktu habis. Tapi ping ke host ip antarmuka docker0 bekerja. Juga menggali dengan ip docker0 yang sama dari karya host buruh pelabuhan. Apakah Anda punya saran?
Satheesh
1
@Satheesh Mungkin setelan firewall Anda yang mencegah container meminta DNS dari host?
xuhdev
@xuhdev terima kasih itu adalah firewalld di mesin host saya, yang menyebabkan masalah. Setelah saya menghentikan firewalld, penampung saya berkomunikasi dengan dnsmasq di host
Satheesh
206

Fitur jaringan baru memungkinkan Anda untuk terhubung ke kontainer berdasarkan namanya, jadi jika Anda membuat jaringan baru, semua kontainer yang terhubung ke jaringan itu dapat menjangkau kontainer lain dengan namanya. Contoh:

1) Buat jaringan baru

$ docker network create <network-name>       

2) Hubungkan kontainer ke jaringan

$ docker run --net=<network-name> ...

atau

$ docker network connect <network-name> <container-name>

3) Ping container dengan nama

docker exec -ti <container-name-A> ping <container-name-B> 

64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms

Lihat ini bagian dari dokumentasi;

Catatan: Tidak seperti lama links, jaringan baru tidak akan membuat variabel lingkungan, atau membagikan variabel lingkungan dengan penampung lain.

Fitur ini saat ini tidak mendukung alias

Hemerson Varela
sumber
4
Bekerja dengan baik. Mengapa jaringan default tidak mengaktifkan ini secara default ??
Stéphane
Bagian yang kurang jelas adalah, Anda perlu memulai ulang aplikasi yang berjalan di penampung yang berbeda. Jadi, bagaimana wadah A membuat aplikasi yang berjalan di wadah B dapat dimulai ulang? Jelas, tampaknya ada kebutuhan akan bus komunikasi. Yang paling saya pikirkan adalah menggunakan Redis untuk pensinyalan dan komunikasi antar-kontainer .. Jadi semua kontainer berlangganan saluran redis dan di sanalah mereka akan berbicara ... Bagaimana dengan perubahan pada port yang dipublikasikan di galangan-tulis file .yml membutuhkan lengkap docker-compose down,up,restart?
eigenfield
inilah yang saya cari-cari sepanjang hari! tidak tahu Anda dapat merujuk ke node jaringan dengan nama / id penampungnya. Terima kasih!
Elliotwesoff
1
@ Stéphane Hal ini cacat di default bridgejaringan karena kompatibilitas mundur tapi ya, saya setuju, itu harus pasti akan diaktifkan secara default!
helmesjo
15

Yang harus apa --linkbagi , setidaknya untuk bagian hostname.
Dengan buruh pelabuhan 1,10, dan PR 19242 , itu akan menjadi:

docker network create --net-alias=[]: Add network-scoped alias for the container

(lihat bagian terakhir di bawah)

Itulah yang memperbarui/etc/hosts detail file

Selain variabel lingkungan, Docker menambahkan entri host untuk penampung sumber ke /etc/hostsfile.

Misalnya, luncurkan server LDAP:

docker run -t  --name openldap -d -p 389:389 larrycai/openldap

Dan tentukan gambar untuk menguji server LDAP tersebut:

FROM ubuntu
RUN apt-get -y install ldap-utils
RUN touch /root/.bash_aliases
RUN echo "alias lds='ldapsearch -H ldap://internalopenldap -LL -b
ou=Users,dc=openstack,dc=org -D cn=admin,dc=openstack,dc=org -w
password'" > /root/.bash_aliases
ENTRYPOINT bash

Anda dapat mengekspos ' openldap' container as ' internalopenldap' dalam gambar uji dengan --link:

 docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest

Kemudian, jika Anda mengetik 'lds', alias itu akan berfungsi:

ldapsearch -H ldap://internalopenldap ...

Itu akan mengembalikan orang. Makna internalopenldapdicapai dengan benar dari ldaptestgambar.


Tentu saja, buruh pelabuhan 1.7 akan menambahkan libnetwork, yang menyediakan implementasi Go asli untuk menghubungkan kontainer. Lihat postingan blog .
Ini memperkenalkan arsitektur yang lebih lengkap, dengan Model Jaringan Kontainer (CNM)

https://blog.docker.com/media/2015/04/cnm-model.jpg

Itu akan memperbarui Docker CLI dengan perintah "jaringan" baru, dan mendokumentasikan bagaimana -netbendera " " digunakan untuk menetapkan kontainer ke jaringan.


buruh pelabuhan 1.10 memiliki bagian baru alias Jaringan-lingkup , sekarang secara resmi didokumentasikan dinetwork connect :

Sementara tautan menyediakan resolusi nama pribadi yang dilokalkan dalam wadah, alias cakupan jaringan menyediakan cara agar wadah dapat ditemukan dengan nama alternatif oleh wadah lain dalam lingkup jaringan tertentu.
Tidak seperti alias tautan, yang ditentukan oleh konsumen layanan, alias cakupan jaringan ditentukan oleh wadah yang menawarkan layanan ke jaringan.

Melanjutkan contoh di atas, buat penampung lain isolated_nwdengan alias jaringan.

$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17

--alias=[]         

Tambahkan alias cakupan jaringan untuk penampung

Anda dapat menggunakan --linkopsi untuk menautkan penampung lain dengan alias yang disukai

Anda dapat menjeda, memulai ulang, dan menghentikan kontainer yang terhubung ke jaringan. Kontainer yang dijeda tetap terhubung dan dapat diungkapkan dengan pemeriksaan jaringan. Saat penampung dihentikan, penampung tidak muncul di jaringan sampai Anda memulai ulang.

Jika ditentukan, alamat IP penampung diterapkan kembali saat penampung yang dihentikan dimulai ulang. Jika alamat IP tidak lagi tersedia, penampung gagal untuk memulai.

Salah satu cara untuk menjamin bahwa alamat IP tersedia adalah dengan menentukan --ip-rangesaat membuat jaringan, dan memilih alamat IP statis dari luar rentang itu. Ini memastikan bahwa alamat IP tidak diberikan ke penampung lain saat penampung ini tidak ada di jaringan.

$ docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 multi-host-network

$ docker network connect --ip 172.20.128.2 multi-host-network container2
$ docker network connect --link container1:c1 multi-host-network container2
VonC
sumber
3
Masalah --link adalah, Anda tidak dapat memulai ulang penampung tanpa memulai ulang penampung yang ditautkan juga. Saat Anda melihat grafik saya, memulai ulang kontainer MySQL akan menghasilkan rangkaian mulai ulang kontainer lainnya.
Patrick Gotthard
3

EDIT : Ini bukan lagi tepi berdarah: http://blog.docker.com/2016/02/docker-1-10/

Jawaban Asli
Saya berjuang sepanjang malam. Jika Anda tidak takut dengan versi terbaru, versi terbaru mesin Docker dan Docker akan mengimplementasikan libnetwork.

Dengan file konfigurasi yang tepat (yang perlu dimasukkan ke dalam versi 2), Anda akan membuat layanan yang semuanya akan saling melihat. Dan, bonus, Anda dapat menskalakannya dengan docker-compose juga (Anda dapat menskalakan layanan apa pun yang Anda inginkan yang tidak mengikat port pada host)

Berikut adalah contoh file

version: "2"
services:
  router:
    build: services/router/
    ports:
      - "8080:8080"
  auth:
    build: services/auth/
  todo:
    build: services/todo/
  data:
    build: services/data/

Dan referensi untuk file compose versi baru ini: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md

Dolanor
sumber
1

Sejauh yang saya tahu, dengan hanya menggunakan Docker, hal ini tidak memungkinkan. Anda memerlukan beberapa DNS untuk memetakan ip kontainer: s ke nama host.

Jika Anda ingin solusi di luar kotak. Salah satu solusinya adalah dengan menggunakan misalnya Kontena . Muncul dengan teknologi overlay jaringan dari Weave dan teknologi ini digunakan untuk membuat jaringan LAN pribadi virtual untuk setiap layanan dan setiap layanan dapat dijangkau service_name.kontena.local-address.

Berikut adalah contoh sederhana dari file YAML aplikasi Wordpress dimana layanan Wordpress terhubung ke server MySQL dengan alamat wordpress-mysql.kontena.local:

wordpress:                                                                         
  image: wordpress:4.1                                                             
  stateful: true                                                                   
  ports:                                                                           
    - 80:80                                                                      
  links:                                                                           
    - mysql:wordpress-mysql                                                        
  environment:                                                                     
    - WORDPRESS_DB_HOST=wordpress-mysql.kontena.local                              
    - WORDPRESS_DB_PASSWORD=secret                                                 
mysql:                                                                             
  image: mariadb:5.5                                                               
  stateful: true                                                                   
  environment:                                                                     
    - MYSQL_ROOT_PASSWORD=secret
Lauri
sumber