"호스트 이름"을 통해 Docker 컨테이너간에 통신하는 방법


91

모놀 틱 서버를 여러 개의 작은 도커 컨테이너로 분할 할 계획이지만 아직 "컨테이너 간 통신"을위한 좋은 솔루션을 찾지 못했습니다. 이것이 내 목표 시나리오입니다.

대상 시나리오

컨테이너를 함께 연결하는 방법과 포트를 노출하는 방법을 알고 있지만 이러한 솔루션 중 어느 것도 만족스럽지 않습니다.

기존 서버 네트워크에서와 같이 컨테이너간에 호스트 이름 (컨테이너 이름)을 통해 통신 할 수있는 솔루션이 있습니까?


나는 최근에 당신이 찾고있는 것을 정확히 하는 문서를 썼습니다 . 기본적으로 여러 컨테이너 (프로세스 당 하나씩)를 설치하고 통합하는 방법을 문서화합니다. "컨테이너 간 통신"은 게임의 일부입니다 .
xuhdev

방금 Tumtum 블로그를 찾았고 공식 Docker 문서에서이 단락을 발견했습니다 . 나는이 모든 단락 시간을 놓쳤다 여부를 모르거나 그것을 새로 추가되었는지 여부를하지만 내가 :) 필요 정확히해야한다
패트릭 타드

docker 1.10이 나왔고 docker connect는 훌륭합니다 ( github.com/docker/docker/blob/… ). 참조 아래에있는 내 편집 대답
VonC

2
나는 당신이 docker-compose 시도해야한다고 생각합니다 . 아주 잘 작동합니다.
Suhas 치카 나

답변:


27

편집 : Docker 1.9 이후에는 docker network명령 ( https://stackoverflow.com/a/35184695/977939 참조 )이이를 수행하는 데 권장되는 방법입니다.


내 해결책은 DNS 레코드가 자동으로 업데이트되도록 호스트에 dnsmasq를 설정하는 것입니다. "A"레코드에는 컨테이너 이름이 있고 컨테이너의 IP 주소를 자동으로 가리 킵니다 (10 초마다). 자동 업데이트 스크립트는 여기에 붙여 넣습니다 :

#!/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

에서 dnsmasq 서비스를 사용할 수 있는지 확인하십시오 docker0. 그런 다음 --dns HOST_ADDRESS이 미니 DNS 서비스를 사용하기 위해 컨테이너를 시작합니다 .

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


그것은 내 --link 대답보다 흥미롭고 탄력적으로 보입니다. +1
VonC 2015 년

@VonC는 새로운 libnetwork가이 해결 방법을 대체 할 수있는 것처럼 보입니다. 그래도 보자.
xuhdev

@xuhdev docs.blowb.org/setup-host/dnsmasq.html에서와 같이 dnsmasq를 설정 했습니다 . 하지만 도커 컨테이너에서 dig를 사용할 때 문제가 발생하면 시간이 초과됩니다. 그러나 호스트 docker0 인터페이스 ip에 대한 핑이 작동합니다. 또한 docker 호스트에서 동일한 docker0 ip로 발굴하십시오. sugestions가 있습니까?
Satheesh

1
@Satheesh 컨테이너가 호스트에서 DNS를 쿼리하지 못하게하는 방화벽 설정 때문일까요?
xuhdev

@xuhdev 덕분에 내 호스트 컴퓨터에서 방화벽이 발생하여 문제가 발생했습니다. 나는 firewalld 굴복하면 호스트하는 dnsmasq 내 컨테이너가 통신
Satheesh

205

새로운 네트워킹 기능을 사용하면 이름으로 컨테이너에 연결할 수 있으므로 새 네트워크를 만들면 해당 네트워크에 연결된 모든 컨테이너가 이름으로 다른 컨테이너에 연결할 수 있습니다. 예:

1) 새 네트워크 생성

$ docker network create <network-name>       

2) 컨테이너를 네트워크에 연결

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

또는

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

3) 이름 별 핑 컨테이너

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

문서 의이 섹션을 참조하십시오 .

참고 : 레거시와 달리 links새 네트워킹 환경 변수를 생성하지 않으며 다른 컨테이너와 환경 변수를 공유하지 않습니다.

이 기능은 현재 별칭을 지원하지 않습니다.


4
잘 작동합니다. 기본 네트워크가이 기능을 기본적으로 활성화하지 않는 이유는 무엇입니까?
Stéphane

덜 분명한 부분은 다른 컨테이너에서 실행중인 앱을 다시 시작해야한다는 것입니다. 그렇다면 컨테이너 A는 컨테이너 B에서 앱을 다시 시작하도록 만들 수 있습니까? 분명히 일종의 통신 버스가 필요한 것 같습니다. 내 마음의 맨 위에는 신호 및 컨테이너 간 통신을 위해 Redis를 사용하는 것입니다. 모든 컨테이너가 redis 채널을 구독하고 이야기 할 것입니다 ... docker-compose에서 게시 된 포트의 변경 사항은 어떻습니까? .yml 파일에 완전한 docker-compose down,up,restart?
eigenfield

이것이 바로 제가 하루 종일 찾고 있던 것입니다! 컨테이너 이름 / ID로 네트워크 노드를 참조 할 수 있다는 것을 몰랐습니다. 감사합니다!
elliotwesoff

1
@ Stéphane bridge이전 버전과의 호환성으로 인해 기본 네트워크 에서 비활성화되어 있지만 예, 동의합니다. 기본적으로 활성화 해야합니다 !
helmesjo

15

즉해야 무엇을 --link위한 호스트 이름 부분 적어도.
으로 고정 표시기 1.10, 및 PR 19242 , 그 것이다 :

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

(아래 마지막 섹션 참조)

그것이 파일 세부 정보 업데이트/etc/hosts

환경 변수 외에도 Docker는 소스 컨테이너에 대한 호스트 항목을 /etc/hosts파일에 추가합니다.

예를 들어 LDAP 서버를 시작합니다.

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

그리고 해당 LDAP 서버를 테스트 할 이미지를 정의합니다.

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

--link를 사용하여 테스트 이미지 내 에서 ' openldap'컨테이너를 ' internalopenldap' 로 노출 할 수 있습니다 .

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

그런 다음 'lds'를 입력하면 해당 별칭이 작동합니다.

ldapsearch -H ldap://internalopenldap ...

그것은 사람들을 반환 할 것입니다. 이미지 internalopenldap에서 의미 에 올바르게 도달했습니다 ldaptest.


물론 docker 1.7은 libnetwork컨테이너 연결을위한 기본 Go 구현을 제공하는을 추가 합니다. 블로그 게시물을 참조하십시오 .
CNM (Container Network Model)을 통해보다 완벽한 아키텍처를 도입했습니다.

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

그러면 새로운 "network"명령으로 Docker CLI를 업데이트하고 " -net"플래그를 사용하여 컨테이너를 네트워크에 할당 하는 방법을 문서화합니다 .


docker 1.10에는 이제 공식적으로 문서화 된 새로운 섹션 Network-scoped alias 가 있습니다network connect .

링크는 컨테이너 내에서 지역화 된 개인 이름 확인을 제공하지만 네트워크 범위 별칭은 특정 네트워크 범위 내의 다른 컨테이너에서 대체 이름으로 컨테이너를 검색 할 수있는 방법을 제공합니다.
서비스 소비자가 정의하는 링크 별칭과 달리 네트워크 범위 별칭은 네트워크에 서비스를 제공하는 컨테이너에 의해 정의됩니다.

위의 예를 계속 isolated_nw하여 네트워크 별칭을 사용하여 다른 컨테이너를 만듭니다 .

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

--alias=[]         

컨테이너에 대한 네트워크 범위 별칭 추가

--link옵션을 사용 하여 선호하는 별칭으로 다른 컨테이너를 연결할 수 있습니다.

네트워크에 연결된 컨테이너를 일시 중지, 다시 시작 및 중지 할 수 있습니다. 일시 중지 된 컨테이너는 연결된 상태로 유지되며 네트워크 검사를 통해 확인할 수 있습니다. 컨테이너가 중지되면 다시 시작할 때까지 네트워크에 나타나지 않습니다.

지정된 경우 중지 된 컨테이너가 다시 시작될 때 컨테이너의 IP 주소가 다시 적용됩니다. IP 주소를 더 이상 사용할 수 없으면 컨테이너가 시작되지 않습니다.

IP 주소를 사용할 수 있는지 확인하는 한 가지 방법 --ip-range은 네트워크를 만들 때 를 지정하고 해당 범위 외부에서 고정 IP 주소를 선택하는 것입니다. 이렇게하면이 컨테이너가 네트워크에없는 동안 IP 주소가 다른 컨테이너에 제공되지 않습니다.

$ 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

3
--link의 문제는 연결된 컨테이너를 다시 시작하지 않고 컨테이너를 다시 시작할 수 없다는 것입니다. 내 그래픽을 볼 때 MySQL 컨테이너를 다시 시작하면 다른 컨테이너가 계단식으로 다시 시작됩니다.
Patrick Gotthard 2015 년

3

편집 : 더 이상 블리딩 에지가 아닙니다 : http://blog.docker.com/2016/02/docker-1-10/

원래 답변
나는 밤새 그것과 싸웠다. 블리딩 엣지를 두려워하지 않는다면 최신 버전의 Docker 엔진Docker가 모두 libnetwork를 구현합니다.

올바른 구성 파일 (버전 2에 넣어야 함)을 사용하면 서로를 볼 수있는 서비스를 만들 수 있습니다. 또한 docker-compose로 확장 할 수도 있습니다 (호스트의 포트를 바인딩하지 않는 원하는 서비스를 확장 할 수 있음).

다음은 예제 파일입니다.

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

이 새로운 버전의 compose 파일에 대한 참조 : https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md


1

내가 아는 한 Docker 만 사용하면 불가능합니다. 컨테이너 ip : s를 호스트 이름에 매핑하려면 DNS가 필요합니다.

즉시 사용 가능한 솔루션을 원하는 경우. 한 가지 해결책은 예를 들어 Instagrama 를 사용하는 것입니다 . Weave의 네트워크 오버레이 기술과 함께 제공되며이 기술은 각 서비스에 대한 가상 사설 LAN 네트워크를 생성하는 데 사용되며 모든 서비스는 service_name.kontena.local-address.

다음은 Wordpress 서비스가 wordpress-mysql.kontena.local 주소로 MySQL 서버에 연결되는 Wordpress 애플리케이션의 YAML 파일에 대한 간단한 예입니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.