이 글은 Docker를 사용하여 스스로 본인이 공부하며 작성한 일기의 성격을 갖는 글입니다.


왜 Docker?

논문 및 프로젝트 때문에 빅 데이터 아키텍처를 구축해야 한다. 많이 들어는 보았고, 이래 저래 잡다하게 지식이 있기는 한데, 실제로 해본 적은 한 번도 없는 상태!

처음에는 당연히 맨 땅에 헤딩을 했다. 아무 것도 없는 Linux에 이것 저것 설치해서 각각 서비스들끼리 연결하는게 당연하다고 생각했다. 여태까지 그래왔으니깐.

그러한 생각이 최초로 깨진 것은 Drools Workbench를 설치할 때 였다. Java 서버 기반 환경에 익숙하지를 않아서 도대체가 war는 뭐고 왜 tomcat은 잘 안되고 wildfly는 어떻게 동작하고 이걸 DNS랑 맞물려서 Reverse Proxy는 어떻게 해야할 지, 이걸 일일히 설정해주는게 정말 끔찍하게 어려웠다. 하지만 Docker를 사용하니 2주 이상 개고생한 일을 하루이틀만에 끝냈다.

그리고 나서 Docker에 대해 이것 저것 찾아보고 난 뒤, Docker가 끔찍하게 멋지다는 것을 알게 되었다. 그리고 모든 것을 Docker로 해야 겠다는 나름의 확신도 들었다.

사실 지금 논문 때문에 Go를 공부하고 있지 못하지만, 처음에 Go를 알게 되고 Go가 멋지다고 생각한 이유 중 하나도 바로 이 Docker 에 영향을 받았기도 했다. 동적 라이브러리의 사용 대신 정적 라이브러리의 사용으로 단일 바이너리를 만들어서 배포가 굉장히 쉽고, 고루틴으로 멀티 코어 프로그래밍을 굉장히 쉽고, 효율적으로 할 수 있다는 점은 나를 매료시켰다. 그리고 Docker 또한 Go로 만들어졌기 때문에 그러한 특성을 그대로 받는 것이다.

그러면서 한편으로 Docker를 자세하게는 몰랐던 지라 그냥 그 정도로만 알고 있었는데, 책 한 두권과 여러 레퍼런스, 공식 문서들을 참조하며 공부해보니 생각 이상으로 멋진 녀석이었고, 앞으로 서버 쪽 개발 및 배포는 무조건 Docker를 사용하는 점이 좋다고 생각한다.

내가 생각하는 Docker의 멋진 점은 다음과 같다.

  1. 배포하기가 짱짱 좋다.
  2. 개발할 때 좋다.
    • 가령 설치하다 실수를 해도 원상복귀가 아주 쉽다!
    • 다른 서비스와 연동이 굉장히 쉽다!
    • 테스트 할 때마다 어떤 프로그램을 설치할 필요가 없다! --rm 옵션으로 실행시키고 바로 삭제하면 됨.
    • … 그 외에 더 생각나면 추가하겠음.
  3. Git과 연동해서 배포의 자동화 완성 가능! (with Git Hook!)
  4. 형상 관리 시스템! (Git 처럼)
    • 이미지 자체는 단계별로 레이어로 구분되고, 사용자가 그 레이어를 기반으로 무언가를 추가할 때마다 새로운 레이어만 추가되므로, 배포를 할 때에 추가된 부분(레이어)만 받으면 되니 굉장히 좋음.
    • 그리고 Git으로 소스코드 관리하듯, 변화된 부분에 대해 관리할 수가 있으므로 버전 관리가 쩖.
    • Docker Hub
      • Github 마냥, 중앙 관리 시스템이 있음!! (개인적으로 이것은 큰 장점이라 생각한다)

일단 이 정도인 것 같다.

사실 배포하기 좋은 점이 가장 크다. 여태까지 내 인생에서 C, Node를 사용해오면서 대단하진 않지만 이런 저런 프로그램을 만들어왔었다. 사실 C의 경우는 임베디드 프로그래밍에서 주로 사용했기에 배포가 큰 문제가 되진 않았지만, 당장에 Node만 해도 버전 업이 너무나 급격하게 이루어졌기에, 내가 Node로 개발을 시작했던 때에 LTS는 0.10이었는데 중도에는 io.js로 바뀌더니 4.X 대로 바뀌질 않나, 하튼 버전이 요동을 쳐서, 참 배포가 힘들었었다.

Docker는 이러한 배포 문제를 단방에 해결해준다. 그래서 Docker를 쓰세요!

설치

우리가 설치할 버전은 커뮤니티 에디션 버전(CE, Community Edition) 이다. 그 외에 엔터프라이즈 버전(EE, Enterprise Edition)도 있는데, Docker 팀이 관리해줘서 사용하기 훨씬 쉬워진다는 장점과 안정성을 얻는다는 장점이 있다. 이에 대한건 공식 사이트를 참조하시라.

CE의 설치에 대한 자세한 정보는 다음의 문서에 나와 있다. Ubuntu의 경우에는 다음의 쉘 스크립트를 실행하면 설치가 끝난다.

sudo apt-get -y install \
  apt-transport-https \
  ca-certificates \
  curl \
  software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository \
       "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
       $(lsb_release -cs) \
       stable"

sudo apt-get update

sudo apt-get -y install docker-ce

추가적으로, sudo 없이 docker를 사용하려면 사용자 계정을 docker Group 에 추가해준다.

sudo usermod -aG docker $USER
# 이후 로그아웃 후 재 로그인

실행 및 사용하기 (Docker run)

Docker 책을 2권 보았다. 일단 한 권은 이재홍님이 쓰신, 가장 빨리 만나는 Docker 책이고, 다른 한 권은 완벽한 IT 인프라 구축을 위한 Docker 책이다. 둘 다 중앙 도서관에 있었다.

둘 다 책은 좋은데, 가장 빨리 만나는 Docker는 출간 연도가 2014년이다보니 (가장 빨리 만나다보니 지금은 좀 옛날이 되었다…) 기본적인 것들은 현재까지도 동일하나, 상세한 내용 면에서는 좀 많이 달랐다. 따라서 지금 책을 사서 읽기에는 조금 아쉬운 면이 있다. 그래도 이재홍님께서 본인 블로그에 상당 부분 책을 공개 해 놓으셔서, 한번 읽어보기를 추천한다. 완벽한 IT 인프라 구축을 위한 Docker는 2016년에 출간된 책이어서 현재 환경을 잘 반영하고 있고, 책 구성도 빠르게 따라가기에 좋다. 굳이 책을 사자면 후자를 추천.

갑자기 책 이야기를 꺼낸 이유는, Docker를 실행시키고, 사용하기 위해서 필요한 개념적 이해를 책에 떠 넘기기 위해서이다. ㅎㅎ 내가 Docker 전문가도 아닐 뿐 더러 지금 입장으로는 이를 깊게 공부할 여유가 없기에.

아, 그리고 Docker 공식 홈페이지의 문서가 제일 좋다. 초보자가 시작하기에는 어렵긴 한데, 그래서 책을 훑어본 후 공식 홈페이지 문서를 살펴보는 것을 강추한다.


Docker 에서 중요한 개념으로 이미지와 컨테이너가 있는데, 이미지는 OOP에서의 class 개념과 비슷하고 컨테이너는 인스턴스의 개념과 비슷하다 (개념적으로 비슷하다).

Docker를 사용하는데에 중요한 개념은, Github 같은 Docker Hub에서 Docker 이미지를 로컬 컴퓨터로 가져온 후, 로컬 컴퓨터에서 Docker 이미지를 이용하여 Docker 컨테이너를 만들어서 실행시킨다는 것이다. 이 개념만 이해하면 사용하는데에 있어서 기본은 된 것이다.

# Docker 실행 명령어
docker run [OPTION] <컨테이너 이름:태그> [컨테이너 안에서 실행시킬 명령] [파라미터]
# Docker 실행 예시 1
docker run -d --name kafka wurstmeister/kafka:latest
# Docker 실행 예시 2
docker run -it --name ubuntu ubuntu:latest /bin/bash
# Docker 실행 예시 3
docker run -it -p 9050:9050 -p 9051:9051 -e PASSWORD=yourPassword --rm --name tor-client andreas4all/tor-client:latest
# Docker 실행 예시 4
docker run -d -p 80:80 -p 443:443 -v /my/directory/on/host:/usr/share/nginx/html --name nginx nginx:latest

실행 옵션

자세한 내용은 공식 문서를 참조하도록 하고, 여기서는 많이 사용되는 몇 개만 다룬다.

OPTION Description
-i Interative 모드. STDIN (키보드 입력) 을 컨테이너로 전달할 수 있는지에 대한 여부. true or false
-t psuedo TTY. 가상 터미널 모드. 컨테이너 내에 터미널로 접속하려면 필요. true or false
-d Daemon 으로 실행시킬 것인지에 대한 여부. 이 옵션을 주지 않으면 백그라운드로 실행되지 않는다. true or false
–rm 컨테이너의 프로세스 종료 시 컨테이너가 자동으로 삭제될 것인지에 대한 여부. true or false
–name 컨테이너의 이름. String
-p 포트 포워딩. [호스트의 포트]:[컨테이너 내의 포트] 로 옵션 값 지정
-e 환경 변수. [변수명]=[값] 으로 옵션 값 지정
-v 볼륨 설정. [호스트의 디렉토리]:[컨테이너 내의 디렉토리] 로 옵션 값 지정