Docker 좀더 활용하기

이재홍 http://www.pyrasis.com 2014.08.02 ~ 2014.09.20

다른 서버의 Docker 컨테이너에 연결하기

앞에서 설명한 –link 옵션은 같은 서버의 컨테이너끼리 연결하는 옵션입니다. 이번에는 앰배서더 컨테이너(Ambassador Container)라는 것을 이용하여 다른 서버에 있는 컨테이너에 연결해보겠습니다.

앰배서더 컨테이너는 특별한 컨테이너가 아닌 그냥 일반적인 Docker 컨테이너입니다. 앰배서더 컨테이너는 socat이라는 프로그램을 이용하여 TCP 연결을 다른 곳으로 전달하도록 구성되어 있습니다.


그림 6-4 앰배서더 컨테이너 기본 개념

앰배서더 컨테이너의 Dockerfile을 보면 상당히 복잡하게 보이지만 생각보다 간단합니다. docker run 명령을 실행할 때 전달한 환경 변수를 이용하여 socat을 실행하는 셸 스크립트입니다.

CMD env | grep _TCP= | \
    sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat \
    TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/'  \
    | sh && top

docker run 명령에서 --link 옵션을 사용하거나 -e EXAMPLE_PORT_1234_TCP=tcp://192.168.0.10:1234라고 설정해주면 다음과 같이 환경 변수에 포트 정보가 설정됩니다.

env 명령으로 환경 변수를 출력하고, grep 명령으로 _TCP=를 포함하는 문자열을 찾습니다. 그리고 sed 명령으로 정규표현식을 사용하여 문자열에서 포트 번호와 IP 주소를 추출합니다. 그 뒤 추출한 포트 번호와 IP 주소를을 이용하여 socat 명령을 실행합니다.

EXAMPLE_PORT=tcp://192.168.0.10:1234
EXAMPLE_PORT_1234_TCP_ADDR=192.168.0.10
EXAMPLE_NAME=/example_ambassador/example
HOSTNAME=0cf479687cb0
EXAMPLE_PORT_1234_TCP_PORT=1234
HOME=/
EXAMPLE_PORT_1234_TCP_PROTO=tcp
EXAMPLE_PORT_1234_TCP=tcp://192.168.0.10:1234
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

위 예제 환경에서는 socat 명령으로 로컬의 TCP 프로토콜 1234번 포트를 192.168.0.101234번 포트로 데이터를 전달하도록 설정합니다. 이러한 구조를 앰배서더 패턴(Ambassador Pattern)이라 합니다.

그냥 다른 서버의 컨테이너에서 포트를 노출시키고, 해당 포트에 연결하면 간단한데 왜 이렇게 복잡한 방법을 사용할까요? 컨테이너에서 포트를 노출시키면 해당 서버의 IP 주소나 도메인을 알아야 합니다. 이렇게 되면 작성한 애플리케이션의 소스 레벨에서 IP 주소나 도메인을 설정해주어야 합니다. 만약 서버의 IP주소, 도메인이 바뀌면 소스를 수정해야 하는데, 앰배서더 컨테이너를 이용하면 별칭으로 접근하므로 소스를 수정하지 않아도 됩니다. 즉 외부에 있는 서버라도 같은 서버의 Docker 내부망에 있는 것과 같은 효과가 납니다.

socat
socat은 SOcket CAT을 뜻하며 소켓 통신을 다른 채널로 전달하는 프로그램입니다. 채널은 파일, 파이프, 장치(시리얼, pseudo 터미널 등), 소켓(유닉스 소켓, TCP, UDP 등)이 있습니다.

이제 앰배서더 컨테이너를 이용해서 다른 서버의 컨테이너에 연결해보겠습니다. 그리고 원활한 테스트를 위해 Redis를 사용하겠습니다.

먼저 Redis 서버로 쓸 컴퓨터에서 Redis 컨테이너를 생성합니다. 이 서버의 IP 주소는 192.168.0.10이라 하겠습니다.

$ sudo docker pull redis:latest
$ sudo docker run -d --name redis redis:latest

--name redis 옵션으로 컨테이너 이름을 redis로 지정합니다.

Redis 컨테이너를 위한 앰배서더 컨테이너를 생성합니다. svendowideit는 앰배서더 패턴을 만든 사람 이름입니다.

$ sudo docker run -d --link redis:redis --name redis_ambassador \
    -p 6379:6379 svendowideit/ambassador
  • -d 옵션으로 컨테이너를 백그라운드로 실행합니다.
  • --link redis:redis 옵션으로 redis 컨테이너를 redis 별칭으로 연결합니다.
  • --name redis_ambassador 옵션으로 컨테이너 이름을 redis_ambassador로 지정합니다.
  • -p 6379:6379 옵션으로 컨테이너의 6379번 포트와 호스트의 6379 연결하고 외부에 노출합니다.
  • Docker Hub에 있는 svendowideit/ambassador 이미지를 받은 뒤 컨테이너로 생성합니다(docker run 명령은 로컬에 이미지가 없으면 자동으로 이미지를 받아옵니다).

이제 Redis 클라이언트를 사용할 컴퓨터에서 앰배서더 컨테이너를 생성합니다. Redis 서버의 IP 주소는 192.168.0.10입니다.

$ sudo docker run -d --name redis_ambassador --expose 6379 \
    -e REDIS_PORT_6379_TCP=tcp://192.168.0.10:6379 svendowideit/ambassador
  • -d 옵션으로 컨테이너를 백그라운드로 실행합니다.
  • --name redis_ambassador 옵션으로 컨테이너 이름을 redis_ambassador로 지정합니다.
  • --expose 6379 옵션으로 다른 컨테이너에서 6379번 포트에 연결할 수 있도록 설정합니다. 즉 Redis 클라이언트가 이 redis_ambassador 컨테이너의 6379 포트에 접속하게 됩니다. --expose 옵션은 -p 옵션과는 달리 호스트의 포트를 외부에 노출하지 않습니다.
  • -e REDIS_PORT_6379_TCP=tcp://192.168.0.10:6379 옵션으로 IP 주소와 포트를 설정하여 다른 서버에 있는 redis_ambassador 컨테이너에 연결합니다.
  • Docker Hub에 있는 svendowideit/ambassador 이미지 받은 뒤 컨테이너로 생성합니다.

Docker Hub에 Redis 클라이언트만 들어있는 컨테이너도 있습니다. 이 컨테이너를 이용하여 redis_ambassador 컨테이너에 접속합니다.

$ sudo docker run -i -t --rm --link redis_ambassador:redis relateiq/redis-cli
  • -i -t 옵션으로 콘솔에서 입출력을 할 수 있도록 설정합니다.
  • --rm 옵션으로 컨테이너를 실행만 하고 컨테이너 자체는 삭제합니다. Redis 클라이언트처럼 1회성으로 사용할 때 편리합니다.
  • --link redis_ambassador:redis 옵션으로 redis_ambassador 컨테이너를 redis 별칭으로 연결합니다.
  • Docker Hub에 있는 relateiq/redis-cli 이미지를 받은 뒤 컨테이너로 생성합니다.

Redis 클라이언트가 실행되면 ping 명령을 입력합니다. 결과로 PONG이 출력되면 다른 서버의 Redis 컨테이너에 정상적으로 연결된 것입니다.

redis 172.17.0.4:6379> ping
PONG
redis 172.17.0.4:6379>

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

30 November 2014