toggle menu

[Docker] Docker 시작하기

2016. 7. 3. 17:08 Docker

들어가며


전부터 Docker 기반으로 개발/배포 환경을 꾸미고 싶었는데, 최근에서야 Docker 기반으로 몇개의 작은 프로젝트를 구성하고 배포해보고 있다. 사용해 본 시간이 길지는 않지만, 그간 손에 익힌 내용들을 정리해서 공유해보려고 한다.


Docker는 오픈 소스 컨테이너 가상화 플랫폼.. 이라고 공식 문서에서 표현하고 있다. 리눅스 컨테이너 기반으로 OS 레벨은 공유하고 어플리케이션 레벨은 격리해서 실행할 수 있는 가상화 플랫폼으로 Host OS 위에 Guest OS 를 띄우는 다른 가상화 방식과 성능과 효율면에서 매우 뛰어나다.


Docker는 개발 라이프 사이클을 빠르게 가져갈 수 있도록 도와준다. Docker는 개발자가 실환경과 거의 동일하게 구성된 로컬 컨테이너에서 개발할 수 있도록 도와주고 같은 방식으로 생성된 Docker 이미지를 기반으로 쉽게 배포(혹은 이전 상태로 롤백)할 수 있도록 해준다.


공식 문서에서는 아래와 같은 예를 들고 있다.

개발자가 로컬 코드를 쓰고 Docker에서 개발 스택을 동료와 공유합니다. 준비가 되면 코드와 스택을 개발 환경에서 테스트 환경으로 이동하여 개발 환경의 스택을 테스트 환경으로 이동하고 필요한 테스트를 실행합니다. 테스트 환경 후에, Docker 이미지를 프로덕션 환경에 보내고 코드를 배포 할 수 있습니다.


아래에서부터 이어지는 내용은 김대권님이 작성하신 포스팅의 내용을 다시 실행해가며 내가 이해한대로 정리한 수준이다. (Docker 입문자를 위해 좋은 글을 써주신 김대권 님께 감사의 말씀을 전하고 싶다)




설치


기본적으로 리눅스 기반에서 설치하는 것이 가장 쉽고 단순하다.

# Docker 사이트에서 제공하는 쉘스크립트를 사용해서 설치하거나,
$ sudo apt-get install curl
$ curl -fsSL https://get.docker.com/ | sh
$ curl -fsSL https://get.docker.com/gpg | sudo apt-key add -

# 혹은 패키지 매니저를 통해 설치
$ apt-get install docker.io

# 경우에 따라 Docker 가 사용하는 포트에 대해 방화벽 해제가 필요할 수 있다.
$ sudo ufw allow 4243/tcp


맥이나 윈도우에서는 Docker 에서 제공하는 Docker Toolbox 를 설치해서 실행할 수 있다. Docker Toolbox는 Mac OSX와 Windows를 위한 Docker Engine, Machine, Compose 등 Docker 도구를 제공하며 Linux 환경을 구성하기 위해 VirtualBox 를 기반으로 동작한다. 아래 링크의 설명을 따라 Toolbox를 설치할 수 있다.


https://docs.docker.com/toolbox/overview/





Docker 의 세가지 구성 요소


Docker 를 이해하려면 세 가지 구성 요소를 알 필요가 있다. Docker 이미지, Docker 레지스트리, Docker 컨테이너 인데, 하나씩 살펴보도록 하자.



Docker 이미지

Docker 이미지는 읽기 전용(read-only)의 템플릿이다. Ubuntu를 클린 설치한 상태를 이미지로 만들어놓을 수 있고, Ubuntu에 Apache를 설치한 상태를 이미지로 만들어 놓을 수도 있다. 또 다른 사람이 이미 만든 Docker 이미지를 다운로드 할 수도 있다. 이 이미지를 기반으로 Docker 컨테이너를 동작시키게 된다. 또 컨테이너에 변경된 내역들을 다시 이미지화할 수 있다.


Docker 컨테이너

Docker 컨테이너는 디렉토리와 비슷하다. Docker 컨테이너는 프로그램의 실행에 필요한 모든 것을 담고 있게 된다. 각 컨테이너는 Docker 이미지에 의해 만들어지고 실행, 시작, 정지, 이동, 삭제할 수 있다. 각 컨테이너는 독립적이고 안전한 애플리케이션 구동 환경이다.


Docker 레지스트리

Docker 레지스트리는 이미지를 보관한다. 공개 또는 비공개로 보관 이미지의 업로드와 다운로드가 가능하다. 공개 Docker 레지스트리로 Docker Hub 가 제공되고 있어서 자신이 만든 이미지를 공유하거나, 다른 사람이 만든 이미지를 받아서 사용할 수도 있다. 물론 내부용으로 레지스트리를 구성해서 사용하는 것도 가능하다.



정리해보면, Docker 이미지는 읽기 전용 템플릿이고, 이 이미지를 사용해서 Docker 컨테이너를 시작하게 된다. Docker 이미지는 Docker Hub 라는 공개 레지스트리에서 받거나 올릴 수 있고, 내부용으로 레지스트리를 구성할 수 있다.


각 Docker 이미지는 레이어 스택으로 구성되어 있는데, Docker는 유니온 파일 시스템(UnionFS)을 사용해서 이러한 레이어들을 하나의 이미지로 연결하게 된다. Docker가 가벼운 이유 중 하나가 이러한 레이어 덕분인데, 가상 머신에서 어떤 작업을 하면, 이미지를 교체하고 전체를 재구축 하는게 아니라 단순히 레이어를 추가하거나 업데이트하기 때문이다.




이미지 가져오기


앞서 이야기한 공개 Docker 레지스트리인 Docker Hub 에서 ubuntu 이미지를 받아보자.

$ docker pull ubuntu

위의 같은 명령을 통해 ubuntu 이미지를 Docker Hub에서 가져올 수 있다.

Using default tag: latest
latest: Pulling from library/ubuntu

f069f1d21059: Pull complete 
ecbeec5633cf: Pull complete 
ea6f18256d63: Pull complete 
54bde7b02897: Pull complete 
Digest: sha256:bbfd93a02a8487edb60f20316ebc966ddc7aa123c2e609185450b96971020097
Status: Downloaded newer image for ubuntu:latest




이미지 목록보기


docker images 명령을 통해 현재 시스템에 존재하는 도커 이미지 목록을 확인할 수 있다.

$ docker images

ubuntu 이미지를 정상적으로 받았다면 아래와 같이 표시될 것이다.

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              0f192147631d        3 days ago          132.8 MB




컨테이너 생성/실행하기


docker run 명령어로 우분투 이미지를 기반으로 컨테이너를 실행할 수 있다. 옵션 중 -i 는 인터렉티브 모드, -t 는 tty 모드를 의미한다. 마지막 /bin/bash 는 ubuntu 이미지를 기반으로 컨테이너 생성이 완료되면, bash 쉘을 실행하라는 의미이다.

$ docker run -i -t ubuntu /bin/bash

마치 ubuntu 가 설치되어 bash shell 을 사용하고 있는 것과 동일하게 ls 등의 명령도 잘 동작하는 것을 볼 수 있다.

root@51f25d6d6eb3:/# ls
bin  boot  core  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@51f25d6d6eb3:/# exit




컨테이너 목록보기


docker ps 명령어로 현재 실행되고 있는 도커 컨테이너의 목록을 볼 수 있다.

$ docker ps

아마도 컨테이너에서 exit 명령어로 빠져나왔다면 컨테이너가 종료되었기 때문에 실행되고 있는 컨테이너를 보여주는 docker ps 명렁으로는 컨테이너가 보이지 않을 것이다. 종료된 컨테이너를 포함해서 모든 컨테이너 목록을 보고 싶을 때는 -a 옵션을 추가하면 된다.

$ docker ps -a 

위의 명령어로 과거 실행되었던 컨테이너까지 볼 수 있다.

CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                      PORTS               NAMES
51f25d6d6eb3        ubuntu              "/bin/bash"         About a minute ago   Exited (0) 27 seconds ago                       jolly_bardeen




종료된 컨테이너 다시 실행하기


docker restart 명령을 통해 종료된 컨테이너를 다시 실행시킬 수도 있다.

$ docker restart 컨테이너id

이제 docker ps 명령으로 해당 컨테이너가 다시 실행된 것을 볼 수 있다.

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
51f25d6d6eb3        ubuntu              "/bin/bash"         2 minutes ago       Up 2 seconds                            jolly_bardeen

컨테이너 안으로 다시 들어가기 위해서는 attach 명령을 사용해야 한다.

$ docker attach 컨테이너id

컨테이너 안으로 다시 들어가면 아래와 같이 다시 bash shell 이 실행되어 ls 명령 등을 실행할 수 있는 것을 볼 수 있다.

root@51f25d6d6eb3:/# ls
bin  boot  core  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@51f25d6d6eb3:/# exit




이미지 생성하기


생성된 컨테이너에서 node.js 등 필요한 툴들을 설치하고 난 뒤 변경된 컨테이너의 상태를 그대로 이미지화 할 수 있다.


기존 원본 이미지와 현재 컨테이너의 상태가 어떻게 다른지 diff 명령을 사용해서 확인해 보자. 이전 백업과의 차이점만을 저장하는 Git의 증분백업과 매우 유사한 형태임을 알 수 있다.

$ docker diff 컨테이너id

만약 이 포스팅에서 처럼 ls 정도만 입력했었다면 아래와 같이 bash history 정도의 변경만 있을 것이다.

C /root
A /root/.bash_history

이제 변경된 컨테이너의 상태를 그대로 이미지로 생성하는 것은 commit 명령을 사용한다.

$ docker commit 컨테이너id 레파지토리명/이미지이름:이미지태그




컨테이너 삭제하기


이미지를 기반으로 생성된 컨테이너가 하나라도 존재하면 해당 이미지는 삭제할 수 없다. 따라서 이미지를 삭제하기 전에 먼저 해당 이미지를 기반으로 생성된 컨테이너들을 삭제해야 한다. 컨테이너 삭제는 rm 명령을 사용한다.

$ docker rm 컨테이너id




이미지 삭제하기


이미지를 삭제하는 것은 rmi 명령을 사용한다.

$ docker rmi 이미지이름:이미지태그




마치며


지금까지 Docker 에 대한 기본적인 개념부터 시작해서 Docker 이미지를 받아서 컨테이너를 생성하고 또 변경된 컨테이너를 기반으로 새로운 이미지를 만들어보는 것까지 기본적인 Docker 사용 방법 전반에 대해 살펴보았다. 아직까지는 Docker가 가진 잠재력이 크게 느껴지지 않을지도 모른다. 하지만 다음 포스팅에서 다룰, 하나의 시스템 이미지 구성을 코드화해서 관리할 수 있는 Dockerfile 까지 익히고 나면 애플리케이션을 배포하는 방식에 대해 이전과 다른 안목을 갖게 될 것이라 확신한다.



Docker 관련 포스팅 더보기