본문으로 바로가기

Docker + Jenkins

category DevOps/Docker 2018. 3. 2. 10:37

Docker란?


1. Docker

docker는 컨테이너 기반 가상화 도구이다. 기존에 사용하던 가상 머신(VM)은 사용하기 위해서 항상 OS를 설치해야 했고, 이미지 안에 OS가 포함되어 있기 때문에 용량이 매우 크고 속도도 느리다.

이에 비해 도커는 반가상화보다 더 경량화된 방식을 사용한다. 도커는 OS 전체를 가상화하지 않고 컨테이너라는 리눅스 커널 레벨에서 제공하는 격리된 가상 공간을 사용한다. 

게스트 OS를 설치하지 않기 때문에 호스트와 속도 차이도 거의 없으며 기존의 VM에 비해서는 월등한 속도로 동작한다.

도커는 리눅스 컨테이너를 기반으로 이미지를 편리하게 관리하고 배포할 수 있다.

또한 도커를 사용할 수 있는 환경만 있다면 어플리케이션에 대한 이미지를 pull 받아서 바로 사용할 수 있다.

이는 악성코드 분석 등의 보안 분석 어플리케이션에도 해당되는데, 이런 이유로 도커는 악성코드 분석에 있어서 큰 장점을 지닌다. 또한 도커 이미지에 실행을 위한 구성들과 종속관계가

포함 되어 있기 때문에 사용자가 직접 패키지를 인스톨하고 트러블슈팅 할 필요가 없다. 


2. 도커 이미지(Image), 컨테이너(Container)

도커 이미지(Image)는 필요한 프로그램, 라이브러리, 소스 등을 설치한 뒤에 이를 파일로 만든 것이다.

이렇게 만든 이미지를 레파지토리에 올리고, 레파지토리에 올라와 있는 다른 이미지를 받을 수도 있다. 이렇게 받은 이미지를 도커에서 실행시킨 뒤 사용하면 되는 것이다.

이 때 이미지가 실행된 상태가 컨테이너(Container) 이다. 이미지를 여러 번 실행시키면 하나의 여러 개의 컨테이너가 만들어진다. 운영체제로 본다면 이미지는 일종의 실행파일, 컨테이너는 프로세스와 유사한 개념이다.


3. 도커 아키텍쳐(Docker Architecture)




Client : 도커 Container를 관리하고 실행하기 위해서 Daemon과 상호작용하는 Binary 파일이다.

Registry : 도커 Image가 저장되어 있는 장소이다. 대표적으로 Docker Hub가 있다. Registry는 Public Registry와 Private Registry가 있다.

Daemon : Host에 설치되어 도커 Container를 관리하는 daemon 프로세스이다. Client와 상호작용한다.

Image : 도커 Daemon을 통해 Container로 실행 가능하도록 필요한 프로그램, 라이브러리, 소스 등이 설치된 파일이다.

Container : Image를 실행한 상태이다. 


4. 도커의 장점


- 빠른 설치 (Rapid Application Deployment)

어플리케이션을 설치하고 사용하는 것에 최소의 시간과 용량을 소비한다.


- 어플리케이션 이식성(Portability Across Machines)

어플리케이션과 설치 파일들이 하나의 컨테이너에 존재하기 때문에 호스트의 커널이나 플랫폼 버젼 등에 상관 없이 도커만 실행할 수 있으면 사용이 가능하다.


- 버젼제어, 컴포넌트 재사용(Version Control & Component Reuse)

컨테이너 버젼 제어가 쉽고 변경 내역을 확인 가능하며 롤백이 간단하다. 이전 레이어에서 컴포넌트들을 재사용하기 때문에 도커를 가볍게 만들 수 있다.


- 쉬운 유지관리(Simplified Maintenance)

어플리케이션 종속성에 관한 문제들에 대해 유지관리가 쉽다.


Jenkins란?


젠킨스는 소프트웨어 개발 시 지속적으로 통합 서비스를 제공하는 툴이다. CI(Continuous Integration) 툴 이라고 표현한다.

다수의 개발자들이 하나의 프로그램을 개발할 때 버전 충돌을 방지하기 위해 각자 작업한 내용을 공유영역에 있는 저장소에 빈번히 업로드함으로써 지속적 통합이 가능하도록 해준다.

젠킨스와 같은 CI툴이 등장하기 전에는 일정시간마다 빌드를 실행하는 방식이 일반적이었다.

특히 개발자들이 당일 작성한 소스들의 커밋이 모드 끝난 심야 시간대에 이러한 빌드가 타이머에 의해 집중적으로 진행되었는데, 이를 nightly-build라 한다.

하지만, 젠킨스는 정기적인 빌드에서 한발 나아가 서브버전, Git 과 같은 버전관리시스템과 연동하여 소스의 커밋을 감지하면 자동적으로 자동화 테스트가 포함된 빌드가 작동되도록 설정할 수 있다.

젠킨스가 주는 이점

개발중인 프로젝트에서 커밋은 매우 빈번히 일어나기 때문에 커밋 횟수만큼 빌드를 실행하는 것이 아니라 작업이 큐잉되어 자신이 실행될 차례를 기다리게 된다

코드의 변경과 함께 이뤄지는 이 같은 자동화된 빌드와 테스트 작업들은 다음과 같은 이점들을 가져다 준다.


  • 프로젝트 표준 컴파일 환경에서의 컴파일 오류 검출
  • 자동화 테스트 수행
  • 정적 코드 분석에 의한 코딩 규약 준수여부 체크
  • 프로파일링 툴을 이용한 소스 변경에 따른 성능 변화 감시
  • 결합 테스트 환경에 대한 배포작업

이 외에도 젠킨스는 500여가지가 넘는 플러그인을 온라인으로 간단히 인스톨 할 수 있는 기능을 제공하고 있으며 파이썬과 같은 스크립트를 이용해 손쉽게 자신에게 필요한 기능을 추가 할 수도 있다.

각종 배치 작업의 간략화

프로젝트 기간 중에 개발자들은 순수한 개발 작업 이외에 DB셋업이나 환경설정, Deploy작업과 같은 단순 작업에 시간과 노력을 들이는 경우가 빈번하다.

데이터베이스의 구축, 어플리케이션 서버로의 Deploy, 라이브러리 릴리즈와 같이 이전에 CLI로 실행되던 작업들이 젠킨스 덕분에 웹 인터페이스로 손쉽게 가능해졌다.

Build 자동화의 확립

빌드 툴의 경우 Java는 maven과 gradle이 자리잡고 있으며, 이미 빌드 관리 툴을 이용해 프로젝트를 진행하고 있다면 젠킨스를 사용하지 않을 이유가 하나도 없다. 젠킨스와 연동하여 빌드 자동화를 통해 프로젝트 진행의 효율성을 높일 수 있다.

자동화 테스트

자동화 테스트는 젠킨스를 사용해야 하는 가장 큰 이유 중 하나이며, 사실상 자동화 테스트가 포함되지 않은 빌드는 CI자체가 불가능하다고 봐도 무방하다.

젠킨스는 Subversion이나 Git과 같은 버전관리시스템과 연동하여 코드 변경을 감지하고 자동화 테스트를 수행하기 때문에 만약 개인이 미처 실시하지 못한 테스트가 있다 하여도 든든한 안전망이 되어준다.

제대로 테스트를 거치지 않은 코드를 커밋하게 되면 화난 젠킨스를 만나게 된다.

코드 표준 준수여부 검사

자동화 테스트와 마찬가지로 개인이 미처 실시하지 못한 코드 표준 준수 여부의 검사나 정적 분석을 통한 코드 품질 검사를 빌드 내부에서 수행함으로써 기술적 부채의 감소에도 크게 기여한다.

빌드 파이프라인 구성

2개 이상의 모듈로 구성되는 레이어드 아키텍처가 적용 된 프로젝트에는 그에 따는 빌드 파이프라인 구성이 필요하다.

예를 들면, 도메인 -> 서비스 -> UI와 같이 각 레이어의 참조 관계에 따라 순차적으로 빌드를 진행하지 않으면 안된다.

젠킨스에서는 이러한 빌드 파이프라인의 구성을 간단히 할 수 있으며, 스크립트를 통해서 매우 복잡한 제어까지도 가능하다.




[기존의 방식1 : 코드 변경 적용 시]



  1. push를 한다. (To git)
  2. 테스트 서버에서 war파일을 만든다.
  3. Local이나 이런 곳에 war파일을 받는다.
  4. 운영 서버에 적용시킨다.
  5. 잘 되는지 확인.



[기존의 방식2 : DB통합 시]

  1. 운영서버의 DB를 백업한다.
  2. 서버를 내린 후, 통합 작업을 거친다.
  3. 실패하면 될 때까지 한다...



[도커의 방식1 : DB통합 시]


Blue-Green 배포 (무중단배포)

nginx와 docker-gen을 이용한다. - 여기서 따로 다루지는 않겠다.

(nginx - 로드밸런서, docker-gen - docker의 기본 기능을 적극 활용한 service discovery 툴)


컨테이너 앞단에 nginx를 두고 docker-gen을 이용하여 nginx의 설정파일을 변경하고 프로세스를 재시작한다.

blue 컨테이너 실행 > docker-gen 이벤트 수신 > nginx 설정파일에 blue container 정보 추가 > nginx 재시작

이어서,

green 컨테이너 중지 > docker-gen 이벤트 수신 > nginx 설정파일에 green container 정보 제거 > nginx 재시작


무중단 배포 완성!




[도커의 방식2(+Jenkins) : 코드 변경 적용 시]


도커 + 젠킨스를 사용하는 Workflow를 보면,

1. 개발자가 개발을 하고 소스를 Git에 커밋한다.

2. Jenkins로 Docker 이미지로 빌드한다.

3. 자동 빌드된 Docker 이미지로 테스트 서버에서 테스트를 수행한다.

4. 테스트가 완료되면 해당 이미지를 운영 서버에 배포한다.


이렇게 되면, 개발자가 개발한 소스는 자신의 로컬 PC에서 이미지와 컨테이너를 생성하여 운영 환경과 동일한 상태에서 개발을 할 수 있다.

개발-테스트-운영 환경이 Docker라는 공통된 도구를 사용하게 때문에 서버 환경이 달라서 생기는 각종 문제를 방지할 수 있다.

또한, 빌드된 소스가 이미지라는 형태로 손쉽게 관리 및 이동이 가능하기 때문에 보다 유연한 관리가 가능하다.

따라서 Docker만 설치되어 있으면 어디든지 해당 시스템을 명령어 한두 번 만으로 손쉽게 이전할 수 있다.


[도커의 방식3 : 서비스 문제에 대한 점]


기존의 방식으로 운영을 하면, 한 서비스가 문제가 되면 이 영향이 전체에 가게 된다. (ex. 서비스1, 서비스2 에서 1개에 문제가 일어나면 전체에 영향을 끼친다.)
→ 도커에선 컨테이너 별로 서비스를 올리면 된다. 그러면 문제가 생겨도 다른 서비스에 영향을 주지 않는다.
→ 기존방식에서도 서버를 여러 개로 늘리면 되긴 하지만, 1서버에서 도커로 해결할 수 있고, 그러면 서버의 성능을 늘릴 수도 있다!!





참고 자료 : 

1. Docker, AWS-ECR, Jenkins를 이용해서 웹서비스 무중단 배포하기 

2. 도커를 이용한 웹서비스 무중단 배포하기subicura

3. 리눅스 docker 개념과 Architecture 정리 - 복세편살 개발라이프


궁금한 점은 언제든 댓글로 물어보시면 됩니다!

* 단, 공부하면서 정리한 내용이라 틀린 내용이 있을 수 있습니다. 잘못된 점이 있다면 역시 댓글로 달아주세요!!