[networking] “호스트 이름”을 통해 Docker 컨테이너간에 통신하는 방법

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

대상 시나리오

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

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



답변

편집 : 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


답변

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

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새 네트워킹 환경 변수를 생성하지 않으며 다른 컨테이너와 환경 변수를 공유하지 않습니다.

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


답변

즉해야 무엇을 --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


답변

편집 : 더 이상 블리딩 에지가 아닙니다 : 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


답변

내가 아는 한 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


답변