도커 이야기를 더 해볼까요?
앞서 하이퍼바이저와 도커를 비교하면서 도커를 소개했습니다(링크). 가상머신에 비해 도커가 가볍고 빠르다는 것은 알았는데 만약 가상머신을 사용하지 않는 환경에서 도커를 도입하는 것은 무조건적으로 타당할까요? 도커를 사용하는 것의 장점은 무엇이 더 있을까요?
컨테이너가 VM에 비해 가볍고 빠르다는 경량화의 관한 장점은 이미 언급했습니다.
컨테이너는 컨테이너 런타임이 있는 환경에서는 어디서든 실행 가능하므로 애플리케이션의 이식성이 올라간다는 장점을 갖고있습니다. 따라서 애플리케이션 개발 환경/테스트 환경이나 데모 환경 등 높은 이식성이 요구되는 경우부터 검토해 갈 것을 권장드립니다.
애플리케이션의 이식성이란, 애플리케이션이 특정 운영체제나 하드웨어 환경에 종속되지 않고 다양한 환경에서 쉽게 이식될 수 있는 능력을 말한다. 이식성이 높은 애플리케이션은 새로운 환경에서 빠르게 배포할 수 있으며, 특정 플랫폼에 종속되지 않기 때문에 이후 플랫폼 변경 등의 작업에도 유연하게 대처할 수 있다.
그래서 클라우드 시스템과의 친화력도 높은 것이 특징이다.
그뿐 아니라 컨테이너는 확장성이 높습니다. 컨테이너는 필요에 따라 수평적으로(scale-out) 확장 가능하므로, 더 많은 트래픽을 처리하거나 병렬 처리를 수행할 수 있습니다.
마지막으로 컨테이너는 다른 컨테이너와 격리되어 있기 때문에 안정성이 높습니다. 또한 컨테이너 안에서 실행되는 애플리케이션은 호스트와 분리되어 있기 때문에 보안성도 높아집니다.
그러면 많은 컨테이너 기술 중에 왜 도커일까요? 일차원적으로 생각하면 많이 사용해서 입니다.
Docker Hub Hits 5 Billion Pulls(2016/08)
Docker Hub Hits 396 Billion Pulls(2021/02)
굉장히 많은 도커 기반의 오픈소스들이 있고 도커 개발자 커뮤니티가 활성화 되어 있습니다. 어마어마한 사용량으로 사실상 컨테이너 기술의 de facto가 되었습니다.
또 하나의 도커의 장점은 레이어에 있습니다.
도커 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 보통 용량이 수십메가바이트에서 많게는 수기가바이트에 이릅니다.
처음 이미지를 다운받을 땐 크게 부담이 안되지만 기존 이미지에 파일 하나 추가했다고 수 기가바이트를 다시 다운받는다면 끔찍합니다.
도커는 이런 문제를 해결하기 위해 레이어라는 개념을 사용하고 리눅스 커널의 유니온 파일 시스템(UnionFS)을 이용하여 여러개의 레이어를 하나의 파일시스템으로 사용할 수 있게 해줍니다.
이미지는 여러개의 읽기 전용 레이어로 구성되고 파일이 추가되거나 수정되면 새로운 레이어가 쌓입니다. ubuntu 이미지가 A + B + C의 집합이라면, ubuntu 이미지를 베이스로 만든 nginx 이미지는 A + B + C + nginx가 됩니다. webapp 이미지를 nginx 이미지 기반으로 만들었다면 A + B + C + nginx + source 레이어로 구성됩니다.
이러한 읽기 전용 레이어는 다른 이미지와도 공유됩니다. 만약 공통 베이스 이미지를 바탕으로 여러 개의 이미지를 작성한 경우 베이스 이미지의 레이어가 공유됩니다.
이로써 Docker에서는 디스크의 용량을 효율적으로 이용합니다.
이 외에도 public repository를 무료로 사용할 수 있는 레지스트리 docker hub, docker 만의 독자적인 언어(DSL)를 이용해서 이미지 생성 과정을 적을 수 있는 Dockerfile 등 다양한 장점이 있습니다.
Docker 컨테이너는 트래픽의 증감 등에 맞춰 필요할 때 실행하고 필요 없어지면 파기시키는 일회성 운용에 적합합니다. 파기된 컨테이너는 어떤 데이터도 가지고 있지 않습니다. 그 때문에 컨테이너 안은 중요한 영구 데이터를 저장하는 데는 적합하지 않아요.
특히 컨테이너에서 민감한 영구 데이터를 다룰 때 주의해야 합니다. 이것을 해결할 Docker의 기능으로서는 데이터 전용 컨테이너에서 데이터를 관리하는 방법이나 로컬 호스트의 디렉토리를 마운트하여 영구 데이터를 저장해두는 방법 등이 있긴 하지만 어떤 방법으로든 데이터의 증가량이나 I/O량은 어느정도인지, 데이터를 어느 정도를 다중화할지, 어떤 운용으로 백업/복원을 해야 할지를 정해 두는 것이 필요합니다.
Docker는 애플리케이션 실행 환경의 측면에서 보면 트래픽의 변동이 큰 대규모 웹 시스템이나 여러 디바이스로부터 데이터를 처리할 필요가 있는 IoT, 머신 리소스를 유효하게 활용하여 대량의 처리를 단시간에 하는 과학기술계산 분야 등에서 위력을 발휘합니다. 이 때문에 비용 절감을 목적으로 기존 시스템을 이전하는 용도보다 지금까지 없었던 새로운 시스템을 검토하거나 도입하는 용도에 더 적합하다고 할 수 있습니다.
결론은 docker가 만능 열쇠처럼 꼭 도입해야 하는 기술이 아니라 상황에 따라 적재적소에 사용해야 한다는 것입니다.
자! 이제 도커를 도입하겠다는 결론을 내려서 컨테이너를 만들게 되었습니다. 보통 컨테이너 하나에는 하나의 어플리케이션을 가동하는 것이 약속입니다. 그러므로 하나의 컴퓨터에서 여러 어플리케이션을 가동하던 이전의 시스템에서 벗어나 여러 컨테이너를 운용하는 환경을 세팅해야 합니다.
저희가 이번에 다뤄 볼 환경은 네트워크 환경입니다.
Linux는 Docker를 설치하면 서버의 물리 NIC가 docker0이라는 가상 브릿지 네트워크로 연결됩니다. 이 docker0은 Docker가 실행되면 디폴트로 만들어집니다. 컨테이너가 생성이 되면 컨테이너마다 가상 NIC(veth) 또한 생성이 됩니다.
가상 NIC은 docker0과 연결돼고 이는 L2 스위치 처럼 작동합니다. 가상 브릿지는 docker의 NAPT기능을 이용하여 호스트와 컨테이너의 통신이 가능하도록 합니다. 이것은 NAT 라우터와 비슷해 보입니다.
NAPT란
하나의 IP 주소를 여러 컴퓨터가 공유하는 기술로 IP주소와 포트번호를 변환하는 기능이다. NAT는 IP주소를 변환하지만 NAPT는 Port 번호까지 변환해준다. 이는 IP 마스커레이드(가면무도회)라고도 불린다.
도커는 이것을 Linux의 iptables를 사용하여 제공한다.
위에서 설명한 네트워크는 도커의 네트워크 종류 중 브릿지 네트워크의 설명입니다. 이외에도 도커는 호스트 네트워크, Overlay 네트워크를 가지고 있습니다.
docker network ls
를 통해 현재 기본적으로 가지고 있는 네트워크를 나열해 보겠습니다.
여기에 사용자 임의의 네트워크를 생성하여 사용할 수도 있고 기본 네트워크를 사용할 수 있습니다. default는 bridge라는 이름의 bridge 네트워크입니다.
이외에도
등이 있습니다.
기존에 사용하던 bridge 네트워크 말고 새로운 bridge 네트워크를 생성해 보겠습니다.
$ docker network create --driver bridge mybridge
172.20.0.0/16 대역을 가지고 있습니다.
$ docker run -i -t --name mynetwork_container --net mybridge travelping/nettools
새로 생성한 172.20.0.2 ip 주소를 할당 받았습니다.
기본 네트워크는 간단하게 사용할 수 있지만, 여러 컨테이너를 동시에 실행할 경우 IP 충돌이 발생하거나, 보안 문제 등 다양한 이슈가 발생할 수 있습니다.
또한 기본 네트워크를 사용하면 컨테이너 간의 통신이 호스트를 거쳐서 이루어지기 때문에 성능 저하가 발생할 수 있습니다. 이러한 이유로 기본 네트워크 대신 사용 목적에 맞게 새로운 네트워크를 생성하고, 각 컨테이너에 네트워크를 연결하는 것이 좋습니다.
오늘은 docker와 docker network에 대해 공부 해보았습니다. 피드백은 언제나 환영입니다! 읽어주셔서 감사합니다.
참고 :
이미지 출처:
실습에 사용한 이미지 docker-hub: