Docker 컨테이너, Image, Dockerfile

들어가기

Docker 컨테이너 뭐고 Docker Image의 생성 Dockerfile은 어떻게 실행되는지 정리하려고 한다.

Application 환경세팅 문제

우리가 만드는 Application은 실행되는 환경에 따라 OS와 동적 Library에 의존성을 가진다.
즉, Application이 실행되기 위해서는 OS, 동적 Library라는 실행환경이 필요하다.
여기서 문제는 하나의 시스템위에 여러개의 Application을 실행하려고 할때이다.
각 Application이 동일한 라이브러리 버전과 동일한 OS가 필요하다면 상관이 없겠지만
그렇지 않는다고 하면 세팅 지옥의 문이 열린다. (혹시 하나의 Application만 실행하면 되지 라고 생각했다면 간단한 블로그를 띄우려고 해도 WebServer, DB, WebApplication이라는 3개나 필요하다)

세팅 지옥에서 벗어나 깔끔하게 하고 싶다면 Application마다 각각 다른 서버 사용 하면 된다.
하지만 이것도 비용이라는 또 다른 문제가 발생한다.
혹은 가상 머신을 사용하여 환경을 분리해도 되지만 성능이라는 새로운 이슈가 있다.

Docker

컨테이너는 Application의 환경세팅 문제를 해결하고자 나타난 컨테이너 기반의 오픈소스 가성화 플랫폼 이다.

컨테이너

Application의 실행환경의 독립성을 확보해주는 운영체제 수준의 격리 기술 을 말한다.
즉, 실행환경을 실제 구동 환경에서 추상화 하여 Application에게 동일한 인터페이스 를 제공한다.

그럼 가상 머신하고 다른게 뭐냐!! 이것도 성능이슈 있겠네!! 라고 생각 할 수 있다. System layer
하지만 개념상 비슷한 것이지 실질적인 구성을 보면 컨테이너는 가성머신의 Guest OS가 없다 가상머신은 full virtualization(전가상화)방식인 반면 컨테이너는 para virtualization(반가상화) 을 이용하는 방식이다. 즉, Host OS에 작업이 그대로 처리됨으로 Host OS와 거의 동일한 성능을 가진다.
(느라다고 하면 그냥 PC가 느린것이다.!!)

Docker Image

가상머신의 스냅샷과 비슷한 방식으로 컨테이너의 상태를 그대로 저장한 것 입니다.
그렇다고 Image에는 가상 머신과 다르게 운영체제를 포함하고 있지는 않습니다. 그렇기에 훨씬 가벼운 상태가 된다. (생성과 배포의 유리하다) 정리하면 Image는 OS를 포함하지 않고 Application과 라이브러리만 설정값등을 포함된 샌드박스 이다.
운영체제의 자원은 호스트의 자원을 이용하기에 이미지 용량도 줄어들어 배포하기에 부담이 없게된다.

Docker Image layer

Image는 OS가 포함되어 있지 않더라도 Application을 실행하기 위한 모든 파일을 가지고 있기 때문에 보통 용량이 수십에서 수백MB가 된다. 처음 한번은 이미지를 받을 때는 괜찮더라도 이미지 파일에 파일 하나를 추가(혹은 수정)했다고 수백MB를 다시 받는건 말이 안된다.!!

도커는 이 문제를 해결하기 위해서 Layer라는 개념을 사용하였다.
Union File SystemUnion Mount 방식을 이용하였다.

Mount와 Union Mount의 개념을 간단하게 설명하면,
Linux 계열 OS에서는 DOS의 드라이브 개념 대신 하드웨어 장치를 특정 디렉토리로 인식하고 연결 후에 사용하는 걸 Mount라고 하고
특정 디렉토리에 보통 하나의 파일 시스템만 Monut하는게 정상인데 만일 동일한 디렉토리에 둘 이상의 파일 시스템을 마운트하면 항상 마지막에 마운트한 파일 시스템만 보이고 이전 파일 시스템들은 접근 불가 상태가 된다. 이때 Union Mount는 특정 디렉토리에 있는 여러 파일 시스템을 합쳐서 보여주는 것으로 겹치는 파일이 있으면 나중에 들어온 파일시스템순으로 보여준다. 즉, 기존 파일 시스템은 건들지 않고 변경한 내역만 Layer를 쌓듯 저장할 수 있다.

Image layer
Docker의 Image Layer도 동일하게 이전 Layer에 변경한 내역만 저장함으로 Application의 파일이 변경되면 마지막 Layer만 삭제하고 그 이전 Layer 위에 다시 올리면 된다.

Dockerfile

Image를 만드는데 현제 실행중인 컨테이너를 찍어서 만들 수도 있지만
그것보다는 Dockerfile라는 이미지 빌드용 DSL파일을 이용해 관리할 수 있다. (추천)

Dockerfile이란 파일을 현제 폴더에 만들면 docker build -t [name : tag] . 명령을 통해 이미지를 만들 수 있다. docker buildhttps://docs.docker.com/engine/reference/commandline/build/#extended-description명령어를 잘 알고 싶다면 문서를 참조 하면 된다.

간단하게 ubuntu에 OpenJdk 환경과 간단한 설정을 한 Image를 만들어보겠다. Dockerfile이름의 파일을 만들고 아래의 내용을 복붙해보자

# base image 지정
FROM ubuntu:18.04

# apt-get 이용한 openjdk 설치
RUN ["apt-get", "update"]
RUN ["apt-get", "install", "-y" ,"openjdk-8-jdk"]


# 메타 데이터를 추가 / 저자 추가
LABEL maintainer="jaws0910@gmail.com"

# 포트 설정 오픈 설정
EXPOSE 8080

# 리눅스의 /bin/sh -c 혹은 Window의 cmd /S /C로 실행하는 것과 동일하다
RUN echo "HELLO"

cmd 창에 docker build -t openjdk . 명령어를 실행하면 Step 6/6 : RUN echo "HELLO"라며 끝났을 것이다.
하나의 Step이 하나의 Layer가 된다. 즉, 내용이 바뀌게 되면 변경할 필요가 없는 Layer는 기존의 것을 가져다 쓰게 된다.

EXPOSE 8080EXPOSE 8081로 바꾼다음 docker build -t openjdk .을 다시 입력하면 Step 4까지는 Using cache라는 메시지로 기존의 것을 사용하고 Step 5, Step 6이 실행됬을 것이다.

참고로 docker build을 하면 실질적으로 Image를 만들어주는 것은 Docker daemon이다.

마무리

이제 Docker Image를 만드는데 필요한 지식이 어느정도 갖춰진거 같으니 저는 이만!

참고

comments powered by Disqus