본문 바로가기

Docker

docker-compose 를 이용한 개발환경 구축하기 ( feat. vagrant )

이런 경험 다들 있으시죠??




처음 시작은 ... New 구성원이 팀에 배치를 받아 해당 구성원의 PC 에 프로젝트 개발환경을 셋팅해줘야 되는 경우

그런데 하필 운이 없게도.. 팀이 완전히 셋팅되기 전에 프로젝트가 시작되어 개발 도중에 프로젝트 인력이 수시로 추가 되는 경우

더 운이 없게도... 프로젝트가 사이즈가 커서 엄청난 인원의 개발자들이 프로젝트에 중간중간 투입되는 경우

그런데 하필.. 프로젝트 내에서 사용하는 기술 요소가 많아 셋팅해주기도 어렵고 한번에 구동시키기 어려울 경우..

한껏 열받아 있고... 바빠 죽겠는 프로젝트에 신입이 투입되서 옆에서 셋팅이 안되네.. 실행이 안되네... 디버깅이 안되네하며 징징거릴 경우

안그래도 열받아 죽겠는데... 옆에 계신 시니어 개발자님까지 나는 안 발생하는 문제가 자기는 발생한다면서 몇일동안 고생하며 문제를 찾았는데! 그냥 버전이 달라서였던것으로... OTL...

결장타로... 누군가 개발환경에서 잘되서 반영해봤는데 갑자기 상용버전에서 안되는 상황이 발생하는 경우... OTL

너무 과장해서 쓴것 같기도 하네요... ^^;; 아... 이렇게 까지 완벽한 상황이 발생해본적은 없지만... 이럴땐 docker-compose 나 vagrant 가 해결책이 될 수 있습니다!!
(물론 일단 팀장님부터 찾아가서 설득을... ㅎㅎ )


그러면 한번 해봅시다!

이번 포스팅은 docker-compose 를 이용한 개발환경 구축하기를 한번 해보려 합니다. 상황을 한번 가정해 보겠습니다. 3개의 web-service 를 합니다. "root", "api", "admin" 서비스 입니다. 


3개의 프로젝트를 정리해 보면 
  1. Client 용 web-service : root
  2. API 전용 web-service : api
  3. admin web-service : admin

저중에 1,2,3 프로젝트가 하나의 tomcat 위에서 application-context 만 구분하여 서비스 되고 있습니다. 1 번 프로젝트가 묶여서 "/", 2번 프로젝트가 "/api", 3번 프로젝트가 "/admin" 실제는 application-context 를 이렇게 naming 하지 않았지만 일반적인 구성으로 포스팅을 하기 위해 이렇게 했다고 가정해볼게요 +_+ ㅎㅎ



ㅁ 어서 오십쇼! New 구성원님! 개발하기 전에 아래 내용을 셋팅해 주시죠!

보통 새로운 구성원이 오면 개발환경 셋팅을 도와 주어야 합니다. 지금 경우에는 MySQL, Tomcat, Angular 만 셋팅하면 되는 아주 쉬운(?) 상황으로 가정할게요. 하지만 아키텍처가 조금만 복잡해져도 Redis, HDFS 서버, Mongo 등 다양한 셋팅이 붙을 수도 있습니다!

  • Angular 1.x 개발을 위한 Grunt-server
    • angular 1.4.x
    • sass
    • bower
    • npm ( package management 용 )
  • Spring MVC
    • MySQL 5.7.x
    • 스프링이 돌아갈 WAS - 여기서는 Tomcat 8.0.x을 사용

이제 개발자는 머리가 아픕니다 ㅠㅠ 자꾸자꾸 프로젝트에 투입되는 구성원마다 이 셋팅을 도와줘야 되거든요... 


ㅁ 이제는 docker-compose OR vagrant 를 이용해서 편하게 해볼게요!

  ㅇ docker-compose 설치하기


 - 맥의 경우 docker for Mac 을 쓰면 한번에 설치가 되는데 ( 윈도우도! ) 다른 OS 를 쓰는 경우 아래 URL 을 참조하여 설치하면 됩니다.

  ㅇ 이따가 한번 써볼 vagrant 도 설치하기








근데 이게 뭔지는 알고 가자!

Docker-compose 란?

 - 도커 컴포즈는 multi-container Docker applications을 돌리기 위한 Tool 이다.

ㅁ 일반적인 사용 케이스
 - Development environments
 - Automated testing environments
 - Single host deployments
이 중에 우리는 개발환경 구축 에 대해 알아볼거에요 :)


ㅁ docker compose 를 사용하는 방법

  1. Docker file 에 내가 사용할 앱 환경을 정의한다. 여기서 앱 환경이라 함은 내가 하나의 서비스를 돌리는데 필요한 어플리 케이션들을 의미한다 ( 즉, 위에서는 MySQL, Tomcat, Angular 돌리는데 필요한 grunt, npm 등이 되겠다. )
  2. docker-compose.yml 파일에 내가 사용할 앱들을 묶은 서비스를 정의한다.
  3. docker-compose up 명령어를 실행한다!

Sample ( docker-compose.yml )

version: '2'
services:
  web:
    build: .
    ports:
    - "5000:5000"
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis

위 yml 파일 설정과 함께 docker-compose up 명령어를 실행하면 web과 redis 앱을 띄우는 서비스를 실행한다는 것입니다. port 나 링크 등에 대해서는 뒤에서 설명하도록 할게요


Vagrant 란?

Vagrant is a tool for building complete development environments. With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases development/production parity, and makes the "works on my machine" excuse a relic of the past.

 첫문장만 해석해 보면 "vagrant 는 완전한 개발 환경을 만들기 위한 tool 이다"라고 적혀있다. 그런데 사실 vagrant 는 사용하기에 따라 VM 을 편하게 관리하기 위한 tool 정도로 생각할 수 도 있을것 같다.


조대협님 블로그 글(http://bcho.tistory.com/806)을 보면 vagrant 에 대한 간략한 설명과 provisioning 기능을 통해 개발환경을 셋팅하는 좋은 방법에 대해 잘 써있네요! 한번 읽이보면 도움이 되실것 같습니다 :)






0단계 : Spring MVC 프로젝트 생성하기

 - 이미 프로젝트가 존재하는 경우 이 단계는 생략합니다.
 - Spring MVC 프로젝트를 생성합니다. 하나는 ROOT 이고 나머지 둘은 api용, admin용 입니다.
 - 각각의 프로젝트에서 사용되는 ORM or JDBC 설정등을 합니다.
 - 그 이외의 필요한 코드를 작성합니다.
 - Spring MVC 프로젝트를 생성하는 방법 및 코드 작성법은 본 글에서는 다루지 않습니다.


1단계 : Dockerfile 만들기

 - 우리가 쓸 docker 용 MySQL 과 Tomcat 이미지를 만들어야 합니다.. 물론 MySQL 과 Tomcat 의 경우 기본 Base 이미지로 제공되지만 기본설정을 그대로 쓰기에 부족한 부분을 위해! 우리의 이미지로 만들어줄 Dockerfile 을 만들어보자

MySQL 용 Dockerfile

FROM mysql:5.6

# Copy the database initialize script:
# Contents of /docker-entrypoint-initdb.d are run on mysqld startup
ADD  Dump/ /docker-entrypoint-initdb.d/

# Default values for passwords and database name. Can be overridden on docker run
# ENV MYSQL_ROOT_PASSWORD=my-secret-pw # Not defaulted for security reasons!
ENV MYSQL_DATABASE=your_db_name
ENV MYSQL_USER=your_user_name
ENV MYSQL_PASSWORD=your_user_password

  • mysql 5.6 버전을 base image 로 합니다.
  • Dump 폴더안에 sql 을 /docker-entrypoint-initdb.d/ 로 옮겨놓으면 mysql 서버가 start 될 때 저 안의 sql 문을 순차적으로 실행시킵니다.
  • 그리고서 사용할 db와 계정 정보를 ENV 를 통해  추가합니다. 

Tomcat 용 Dockerfile

#FROM pietvandongen/docker-tomcat-development:latest
FROM tomcat:8-jre8
MAINTAINER Sophia Parafina 

# tomcat-users.xml sets up user accounts for the Tomcat manager GUI
# and script access for Maven deployments
# ADD tomcat/tomcat-users.xml $CATALINA_HOME/conf/

# ADD tomcat/catalina.sh $CATALINA_HOME/bin/
ADD tomcat/run.sh $CATALINA_HOME/bin/run.sh
RUN chmod +x $CATALINA_HOME/bin/run.sh

# add MySQL JDBC driver jar
ADD tomcat/mysql-connector-java-5.1.36-bin.jar $CATALINA_HOME/lib/

# create mount point for volume with application
# RUN mkdir $CATALINA_HOME/webapps/UserSignup

# add tomcat jpda debugging environmental variables
ENV JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n"
#ENV JPDA_ADDRESS="8000"
#ENV JPDA_TRANSPORT="dt_socket"

# start tomcat7 with remote debugging
EXPOSE 8080
CMD ["run.sh"]
  • tomcat:8-jre8 이미지를 base 이미지로 합니다.
  • 톰캣 실행 쉘을 추가하고, 실행 권한을 부여한다.
  • mysql connector 를 추가해준다.
  • 원격 디버깅을 위해 JPDA 옵션을 추가해준다. 여기서는 8000 포트를 통해 접근할 수 있도록 설정하였다.
  • 8080 포트를 host 와 연결한다. ( 외부로 노출 되진 않는다! 외부로 노출하는 설정은 docker-compose.yml 파일에서 하도록 한다. )

2단계. docker-compose.yml 파일 만들기

version: "2"

services:

  database:
    build:
      context: ./registration-database
    image: registration-database
    # set default mysql root password, change as needed
    environment:
      MYSQL_ROOT_PASSWORD: password
    # Expose port 3306 to host. Not for the application but
    # handy to inspect the database from the host machine.
    ports:
      - "3306:3306"
    restart: always

  webserver:
    build:
      context: ./registration-was
    image: registration-webserver
    # mount point for application in tomcat
    volumes:
      - ./root/target/root:/usr/local/tomcat/webapps/ROOT
      - ./api/target/api:/usr/local/tomcat/webapps/api
      - ./admin/target/admin:/usr/local/tomcat/webapps/admin
      - ./registration-was/tomcat/logs:/usr/local/tomcat/logs
    links:
      - database:registration-database
    # open ports for tomcat and remote debugging
    ports:
      - "8080:8080"
      - "8000:8000"
    restart: always

  • version 은 왠만하면 2로! ( 참조 : https://docs.docker.com/compose/compose-file/#/version-2 ) 이게 내가 만든 서비시들의 version 이 아니라 compose 의 버전을 몇을 쓸건지 입니다. version 1은 곧 deprecated 될 예정이라고 하네요 :)
  • database ( MySQL ), webserver ( tomcat ) 서비스들을 정의합니다.
  • build > context : Dockerfile 을 포함할 path 입니다. git repository 의 url 로 정의해도 됩니다.
  • image : 이미지 name 입니다. 추후 links 설정시, DB connection 시 필요합니다.
  • ports :  (HOST:CONTAINER) 형식으로 내 호스트로 들어온 포트를 container 의 포트로 포워딩 해주는 설정입니다.
  • restart : always 설정은 container 의 상태에 상관없이 무조건 restart 하겠다는 의미입니다.
  • links : container 에서 다른 container 를 동일한 subnet 이라 가정시 바라 볼 수 있는 hostname 입니다. 아래서 조금더 설명해 보도록 하죠! 

Links 옵션

links 옵션은 해당 서비스가 다른 서비스에 연결하려고 할 때 접근 가능한 추가적인 alias 를 제공해주는 옵션을 의미합니다.
뭔말이야...? 라고 생각할 수 있으니 아래 예시를 하나 보여드리겠습니다.

우리가 Spring MVC 코드 작성시 보통 DB Connection 정보를 적게 되고 거기에 보면 URL 을 적어야 하는 부분이 있습니다. 만약 내가 DB 를 Local ( 127.0.0.1 ) 에 띄운 경우 설정은


3단계. Web-Project property 수정하기

database-connection.properties

...
jdbc.url=jdbc:mysql://127.0.0.1:3306/my_db_name?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=my_name
jdbc.password=my_password


보통 이런식으로 내 로컬주소:포트 를  mysql connection 정보에 적게 됩니다. 하지만 위와 같이 docker-compose 파일을 설정한 경우 위와 같이 connection 정보가 유지 되면 tomcat 에 올라간 웹 서비스가 cannot connect MySQL... 이란 에러를 뱉습니다. 왜 그럴까요...?


...
jdbc.url=jdbc:mysql://registration-database:3306/my_db_name?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=my_name
jdbc.password=my_password
이렇게 적어 주셔야 합니다. 왜냐면 container 가 새로 뜬 docker 에서는 그 container 만의 독립적인 network 환경이 구성되는 것이기 때문에 소스에 적어놓은 ( tomcat container 위에서 돌아가는 나의 소스는 ) 127.0.0.1 은 tomcat container 의 로컬 주소이지 실제 내 PC 의 로컬 주소이거나 mysql container 의 주소가 될 수 없습니다. 그래서 mysql container 의 주소 대신 host name을( registration-database 를 적어주셔야 접근이 됩니다.


...
jdbc.url=jdbc:mysql://database:3306/my_db_name?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=my_name
jdbc.password=my_password
하지만 우리는 Links 에 alias 를 생성했으니 위와 같이 적어도 되겠죠? ^^


4단계 : docker compose up

 - 프로젝트 home folder 로 이동하여 docker compose 를 실행시킵니다. 실행시키는 명령어는 docker-compose up 입니다.
 - docker ps 를 통해 실행되는 container를 확인할 수 있습니다.
$ docker-compose up -d
Starting binswas_database_1
Starting binswas_webserver_1
$ docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                                            NAMES
e0bf7404c258        registration-webserver   "run.sh"                 3 minutes ago       Up 12 seconds       0.0.0.0:8000->8000/tcp, 0.0.0.0:8080->8080/tcp   binswas_webserver_1
cf6a2cc3c4b1        registration-database    "docker-entrypoint.sh"   3 minutes ago       Up 12 seconds       0.0.0.0:3306->3306/tcp                           binswas_database_1

따로 -d 옵션을 붙이지 않은 경우 로그가 찍히며 가동됩니다. 그때는 ctrl + c 만 눌러도 종료된것과 같습니다. 

-d 옵션을 줘서 실행한경우 끄는 명령어는 stop 입니다.

$ docker-compose stop
contianer 를 완전히 삭제하고 싶은 경우 down 을 하시면 container 가 삭제 됩니다.
$ docker-compose down


5단계 : angular 개발 환경 셋팅

이제 angular 의 개발 환경을 한번 셋팅해 보자! 라고 하며 호기롭게 시작하려 했는데... 이게 문제가 하나 있었네요... 

이때 어떤 고민을 했는지 말씀 드려보면... 
나는 grunt server ( node 용 개발 서버 라고 생각하시면 되요 ㅎㅎ ) 를 띄우고 싶을 뿐인데! 
1. 필요한 node module 이 있으니 npm 이 일단 있어야 되고, 
2. 화면에서 쓰는 bower 가 필요하고, 
3.사용하는 grunt build 시에 필요한 compass 의 경우 ruby 의존 성을 가지니 ruby 도 깔아야 한다 ㅠㅠ


그래서 기존의 mac 사용자들의 경우 이와 같은 셋팅을 해야한다.
$ brew update
$ brew install rbenv
$ rbenv install 2.0.0-p451
$ rbenv rehash
$ rbenv global 2.0.0-p451
$ cd {ui_project_home_path}
$ gem update --system
$ gem install compass
$ npm install -g bower grunt-cli
$ npm install
$ bower install
그니까 ubuntu 이미지를 기반으로 된 container 가 필요한데...
뭔가 찜찜하다... +_+;; 이럴거면 그냥 ubuntu 이미지에 tomcat 도 넣고 MySQL 도 넣고 했지...

"내가 이러려고 docker-compose를 썼나 자괴감 들어... "

이때 그래서 고민을 하던게... 
docker-compose 는 개발환경만 되는게 아니고 배포할때도 또 쓸 수 있고,
vagrant 는 그러지 못한다는 점에 착안해서

개발&배포해야될 것은 docker-compose!
개발에만 필요한 것은 vagrant! 에 하기로 했다!

그니까 grunt server 는 개발에만 쓰이는 용도이지 우리가 직접 배포할 때는 grunt 서버를 띄우진 않는다. 최근 유행하는 react 같은 경우도 개발할 때만 webpack 서버를 쓰고 실제로 배포하게 되는 운영서버에서는 webpack을 꼭 쓰지는 않는다. 즉, 개발에만 필요한 것이라는 것이다.

그래서 이런것은 vagrant 에 넣는 것이다. 그러면 나중에 아래와 같이 배포할 때 docker-compose 를 쓸 수 있는 것이다.



Vagrant

Vagrant.configure("2") do |config|
    config.vm.box = "ubuntu/trusty64"
    config.vm.provision :shell, path: "for-vagrant/setup.sh"
    config.vm.provision :shell, path: "for-vagrant/startup.sh", run: "always"
    config.vm.network :forwarded_port, host: 8080, guest: 8080
    config.vm.network :forwarded_port, host: 9000, guest: 9000
    config.vm.network :forwarded_port, host: 9001, guest: 9001
    config.vm.network :forwarded_port, host: 3306, guest: 3306
    config.vm.network :forwarded_port, host: 35729, guest: 35729
    config.vm.boot_timeout=3000
    # config.ssh.insert_key = true
    # config.vm.synced_folder '.', '/vagrant', disabled: true

    config.vm.provider :virtualbox do |vb|
        # vb.gui = true
        # Use VBoxManage to customize the VM. For example to change memory:
        vb.customize ["modifyvm", :id, "--name", "jhipster-devbox"]
        vb.customize ["modifyvm", :id, "--memory", "4096"]
        vb.customize ["modifyvm", :id, "--vram", 64]
        vb.customize ["modifyvm", :id, "--accelerate3d", "on"]
        vb.customize ['modifyvm', :id, '--clipboard', 'bidirectional']
        vb.customize ['modifyvm', :id, '--draganddrop', 'bidirectional']
    end
end


setup.sh

#!/bin/bash

# update the system
apt-get update
apt-get upgrade

export LANGUAGE='en_US.UTF-8'
export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'
locale-gen en_US.UTF-8
dpkg-reconfigure locales

# install utilities
apt-get -y install vim git zip bzip2 fontconfig curl language-pack-en

# install Java 8
echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' >> /etc/apt/sources.list
echo 'deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' >> /etc/apt/sources.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C2518248EEA14886

apt-get update

echo oracle-java-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
apt-get install -y --force-yes oracle-java8-installer
update-java-alternatives -s java-8-oracle


# install rbenv

apt-get install -y autoconf bison build-essential libssl-dev libyaml-dev libreadline6 libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
sleep 3
cd ~/
echo pwd
git clone git://github.com/sstephenson/rbenv.git /root/.rbenv
sleep 3
echo 'export PATH="/root/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
export PATH="/root/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
sleep 3

git clone git://github.com/sstephenson/ruby-build.git /root/.rbenv/plugins/ruby-build
echo 'export PATH="/root/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
export PATH="/root/.rbenv/plugins/ruby-build/bin:$PATH"
sleep 3
source ~/.bashrc


sleep 3
curl -fsSL https://gist.github.com/LeonB/10503374/raw | rbenv install --patch 2.0.0-p451
/root/.rbenv/bin/rbenv rehash
/root/.rbenv/bin/rbenv global 2.0.0-p451


# install node.js
curl -sL https://deb.nodesource.com/setup_4.x | bash -
apt-get install -y nodejs unzip python g++

# update npm
npm install -g npm

# install yeoman grunt bower gulp
npm install -g yo bower grunt-cli

gem update --system
gem install compass

cd /vagrant/bins_ui
bower install
npm install

# install Docker
curl -sL https://get.docker.io/ | sh

# install docker compose
curl -L https://github.com/docker/compose/releases/download/1.8.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# configure docker group (docker commands can be launched without sudo)
usermod -aG docker vagrant

# clean the box
apt-get -y autoclean
apt-get -y clean
apt-get -y autoremove
dd if=/dev/zero of=/EMPTY bs=1M > /dev/null 2>&1
rm -f /EMPTY



# run db, tomcat, grunt serve
cd /vagrant
docker-compose up -d
cd /vagrant/bins_ui
grunt serve



결론!

이럴때 써보니 확실히 좋더라?

  • 프로젝트에 새로운 개발자가 투입되어서 개발환경을 셋팅해 주어야 할 때!
  • 중국에 출장을 갔는데 중국 개발자들과 같이 협업해서 개발해야 될 때
  • 인수인계 해주어야 할 때
  • 셋팅보다 비즈니스 로직에 집중해야 할 때

Docker-compose VS Vagrant

제가 생각하는 답은... 
혼합해서 쓰시면 좋구요 ㅎㅎ 근데 귀찮긴 하잖아요?
그냥 편한거 쓰시면 되요 :)

내가 Docker 좀 공부해봐서 Docker가 편하면 Docker 쓰시구,
VM 좀 잘 알아서 Vagrant 가 편하면 Vagrant 쓰세요!

그래도 기준이 필요하다면

  ㅇ 가벼운걸 원한다면 Docker-compose 를!                                                        

 - 너무나도 잘 아시다시피 Docker 가 VM 에 비해서 가볍습니다. Single VM host 에 많은 application 을 집어넣고 돌리는 거라면 Vagrant 로 해도 상관없지만 여러개의  VM host 가 떠야 한다면... 이렇게 띄웠을때 맥북이 이륙하는 소리가 들린다는.... +_+


                                                                  


Docker 설명하면 매번 나오는 그림이죠 ㅋㅋ VM 에 비해 가볍다. 가볍다. 가볍다. 입니다.


  ㅇ 개발환경에서의 셋팅을 Deploy 셋팅에서도 동일하게 써먹고 싶은 경우

좋은 예시가 있어 아래 링크로 대체 합니다. 간략하게 내용을 설명드리자면 사실 개발환경 셋팅할 때 MySQL을 직접 Local PC 에 깔지 말고 개발 서버에 설치하는 방법도 있어요~! 
( 대기업의 경우 개발용 DB 서버를 따로 신청해야 된다는 번거로움이 있지만... OTL... )
그러면 개발 셋팅이 저희도 Tomcat 만 남겠죠? ( Redis 나 Elasticsearch 도 다 개발용 서버에 미리 깔아두면 되니까요 ㅎㅎ )





subicura 님 블로그에 보시면 php를 동작시키기 위한 nginx( was 서버 ) 와 php와 nginx 연결을 위한 php7-fpm 컨테이너를 compose 로 묶고, 개발환경 뿐 아니라 실 운영서버에서도 docker-compose 를 사용하여 개발환경 = 운영환경을 동일하게 가져가는 고오오급 개발자 다운 ( 자기는 아니라고 하지만.. ㅋㅋ ) 예시를 보여주고 계십니다.




  ㅇ 실행시킨 application에 IP:port 로 직접 접근해야 한다면 Vagrant 를!

개발 하실 때 다들 Mac 쓰시죠?? :) 
그러면 docker 도 설치하실 때 Docker for Mac 으로 설치하셨을 거에요.. (맞으시죠..?ㅠ)

"Docker for Mac 은 docker0 bridge 가 없어요.."

그래서 우리 Local 피씨에서 접속할 수 있는 container 당 IP 주소를 할당이 불가능해요. IP 할당이 불가능하니  container 로 ping 을 때려 볼 수도 없는거죠.. 
( 자세한 내용은 아래 링크를 참조 하세요! )

참조 : https://docs.docker.com/docker-for-mac/networking/



그런데 Vagrant 는 내가 VM에서 network interface 시 사용할 bridge 를 선택하고, 그 아래로 subnet 구성을 설정할 수 있습니다.
... 
...
config.vm.define "hdnode01" do |hdnode|
    hdnode.vm.box = "alonsodomin/ubuntu-trusty64-java8"
    hdnode.vm.network "private_network", ip: "10.x.x.x", :netmask => '255.255.255.0', :bridge => 'en0'

    hdnode.vm.provision "shell", inline: <<-SHELL
      echo HI
      ## 실행 시키고 싶은 명령어!!
    SHELL

    hdnode.vm.provider "virtualbox" do |vb|
      vb.memory = "256"
    end
  end
...
...

이런식으로 설정하시면 java8 이 깔린 ubuntu 이미지를 virtualbox 이미지로 실행시키고 해당 VM은 10.x.x.x 의 IP 주소를 가진 net mask 가 255.255.255.0 ( 즉, network ID 는 10.x.x.0 이 되는 ) subnet 이 구성이 됩니다. 그리고 해당 bridge 는 en0 으로 가져가게 됩니다.

*** 참고! ***
bridge 설정은 자신이 사용하는 컴퓨터 ( 네트워크에 무선이건 유선이건 연결 되있으셔야 해요 ^-^ ) 에서 ifconfig 명령어를 쳐서 확인합니다.
➜  ~ ifconfig
lo0: flags=8049 mtu 16384
	... ...
        ... ...

en0: flags=8863 mtu 1500
	...
        ...

위에 보시면 en0 이라고 있죠? ㅎㅎ 그러면 VM 에서는 기본적으로 en0 network interface 를 이용해서 networking 이 됩니다. 물론 DHCP 등을 통해서도 설정 가능합니다. 해당내용은 아래 링크 참조해주세요!


그러면 이러한 Case 가 뭐가 있을까요??
 
흠.. 쫌 극단적인 예를 한번 들어볼게요 +_+...

운영쪽에 Hadoop Cluster 에 있는 데이터에 접근을 해야 하는 경우. 그리고 아래처럼 Gateway 역할을 해주는 서버가 중간에 자리잡아 운영의 Hadoop Cluster 로 Proxy 를 해주는 구성이 있다고 가정해 봅시다.




그러면 Proxy Server 에 172.1.1.2:9000 으로 쏘면 10.10.10.2:xxxx ( 

DataNode 주소 및 포트 ) 로 proxy 를 겁니다. 

그러니까 예를 들자면 

hdfs://username@172.1.1.2:9000/user/username/app/file/file1.json

뭐 이런식으로 호출을 한다는 거죠. 그런데 Hadoop 은 마스터 Node 에게 file 경로를 주면 master 노드가 해당 파일을 저장하고 있는 slave 파일의 위치를 다시 전송해 줍니다.

(참고 : http://choong0121.tistory.com/entry/Hadoop-File-SystemHDFS )


그럼 만약 파일이 10.10.10.3에 있다고 가정하면 개발존에 있는 hadoop 클라이언트는 10.10.10.3에 해당 파일이 있음을 알게 되고 10.10.10.3:50010 ( 실제 파일이 존재하는 DataNode 주소 및 포트, Hadoop 의 기본 포트가 50010 이다. 설정마다 다른 포트값이 될 수도 있습니다.) 에 접근하려 하지만!!!


Fail.....


개발존에는 10.x.x.x 대역의 network 도 존재하지 않기 때문에 
"이런 ip 주소는 못찾겠는디요.... =_="
하고 에러를 뱉습니다.


이럴 때 "미친척" 하고 vagrant 를 이용해서 이 문제를 해결해 볼수 있는데요.. ㅋㅋ
다시한번 말씀드리지만 정말 설명을 위한 
극단적 상황&해결법이니까 그냥 참고만 해주세요 ... ^^;;




위처럼 vagrant zone 에 10.10.10.x 의 대역대의 네트워크망을 vagrant 를 띄워주고 실제 서버처럼 10.10.10.2 ~ 5 까지 가지고 있는 vagrant VM 들을 띄워주고 이게 리버스 프록시로 Proxy 서버를 바라본다. 그럼 Proxy 서버가 이를 받아서 다시 운영망의 Hadoop Cluster (10.10.10.2 ~ 5:50010)로 연결해 파일을 받아준다.

그러면 개발자 입장에서는 추상적으로(?) 10.10.10.x 대역대를 가진 Hadoop Cluster 가 실제 존재하는 것처럼 개발할 수 있다는 것이다.


자료 출처 & 인용

조대협님 블로그 : http://bcho.tistory.com/806
blues05님 블로그 : http://bluese05.tistory.com/15




아래는 회사에서 발표한 자료 입니다 :)