본문 바로가기
ASAC

[ASAC 06] Docker, CI/CD 기본 개념

by suhsein 2024. 10. 28.
728x90
 이 글은 ASAC 06기를 수강하며 강의 자료 참고 및 추가 자료 수집을 통해 작성된 글입니다. 

 

Docker

  • 이미지 = 어플리케이션 + 어플리케이션을 구동하기 위한 모든 환경적인 요인들
  • 컨테이너 = 자원이 할당되고 실행중인 이미지
  • 이미지와 컨테이너의 차이는 프로그램과 프로세스의 차이와 유사하다. 
    • 이미지는 정적인 프로그램과 유사
    • 컨테이너는 동적인(실행 중인) 프로세스와 유사
  • 컨테이너 혹은 이미지 = 격리의 단위 (일관성 보장 단위)
  • 환경은 두 가지로 구분된다. 
    1. Local(Host) 환경
    2. Docker 환경
  • Docker 버전 = 애플리케이션 버전 + 도커의 환경 버전
  • 하나의 로컬에서 여러 개의 컨테이너 구동이 가능 하지만, 컨테이너가 서로 알려면 네트워크 통신 필요하다. 컨테이너들은 브릿지라고 하는 하나의 컨테이너 환경에 묶여있다. 

 

Docker를 쓰는 이유

1. 일관성 (Consistency)

사람마다 다음과 같은 개발 환경들이 다를 수 있음
어플리케이션 + 어플리케이션을 구동하기 위한 모든 환경적인 요인들을 패키징

 

Docker Image에 포함되는 것들은 다음과 같다.

  • Application 파일 (ex. jar)
  • Environment Variables (환경변수)
  • Runtime Environment (런타임 환경, 버전. ex. jvm)
  • 서드파티 라이브러리
  • Cut-down OS
    • OS 용량은 매우 크다. OS 구동에 필요한 부분만 남긴 요약본 = 커널의 핵심. GUI나 CUI를 모두 날림

무중단 배포 시, 서버를 죽였다 띄우는 경우 인스턴스들이 달라질 수 있다.
Docker 이미지의 경우, 어플리케이션을 구동하기 위한 환경적인 요인들이 통일되어 있기 때문에 어떤 컴퓨터 위에 얹어도 일관성있게 동작한다.

ex) 로컬에서 DB를 갈아 끼우는 것보다는, Docker 이미지를 교체하는 것이 간편함.

 

2. 멀티 컨테이너 (Multi Container) 

다중 컨테이너를 실행할 수 있으므로, DB 서버와 Spring 서버를 각각 두는 대신 하나의 서버 위에서 DB를 위한 이미지와 Spring(어플리케이션)을 위한 이미지를 실행하면 된다. 

상식적으로는 데이터베이스 서버 1개 + WAS 서버 1개를 사용해야 하지만, 하나의 EC2에 DB 컨테이너 + WAS 컨테이너 사용 가능하다. 그러나 이 경우에는 SPoF 문제가 발생할 수 있다. 한 쪽이라도 문제가 발생하면 모든 서비스 이용 불가능

 

  • ex1) WAS + DB
  • ex2) WAS + Logstash
    • ELK 스택 : Logstash(로그 수집, 가공, 전송) + Elastic Search(로그 저장) + Kibana(로그 분석. 일종의 검색 엔진)
    • LogStash = 로그 수집에 이용되는 애플리케이션으로, 각각의 서버에서 발생하는 로그들을 한 곳으로 중앙화하여 검색을 가능케 한다. 대기업에서는 자체 서비스가 존재하기도 하지만, 스타트업에서는 주로 AWS Cloud Watch를 사용한다. 로그들은 반정형(비정형) 데이터이기 때문에, LogStash가 가공도 한다.
  • ex3) 버전이 다른 2개의 동일한 MySQL DB
    • 호스트 port는 다르게 설정해야 함

3. 격리 (Isolation)


로컬 환경과 Docker 환경 간의 격리. 로컬 환경의 오염이나 충돌이 발생하지 않는다.
예를 들어 특정 어플리케이션에서 사용하는 데이터베이스 버전을 맞추기 위해서 기존에는 로컬의 데이터베이스 버전을 맞춰서 재설치 해야하는 수고로움이 있었다면, 도커를 사용하는 경우, 로컬과 도커 환경 간의 격리로 로컬에서 재설치를 할 필요가 없다. 

 

 

격리 가상화 단위 : VM과 Container

 

VM (Virtual Machine) = OS 위의 OS = Guest OS + Bins/Libs + App B

  • 호스트 OS의 하드웨어 자원을 직접 나누어 사용 (HyperVisor에 의해서)
  • Guest OS가 독립적인 하드웨어 자원들을 점유해서 사용하게 된다. => 메모리 접근 충돌 없음. 높은 보안성
  • 무겁다, 느리다

Container = OS 위의 부분 OS = Bins/Libs + App B

  • Docker Engine이 소프트웨어 자원을 소프트웨어적으로 격리하여 사용
  • 컨테이너들은 하나의 OS를 공유한다. 세부적인 구성 요소들은 달리할 수 있지만, 모든 컨테이너들은 공유된 하나의 OS를 사용해야 한다.
  • 가볍다, 빠르다

 

 

윈도우의 Docker 구동

VM 사용 시 Guest OS 구동을 위한 Hypervisor  타입

Docker는 리눅스 기반의 애플리케이션이기 때문에, 실행을 위해서는 리눅스 기반의 개발 환경을 구축해야 한다.

Guest OS를 구동하기 위한 방식은 두 가지가 존재한다.

  1. Baremetal (Microkernalized)
    • 호스트 OS의 하드웨어 자원을 직접 나누어 사용하는 방식
    • 호스트 OS의 하드웨어 위 동작이기에 적은 오버헤드
    • ex) Hyper-V, WSL
  2. Hosted (Monolithic)
    • 호스트 OS의 하드웨어 자원을 소프트웨어적으로 추상화하여 나누어 사용하는 방식
    • 호스트 OS의 하드웨어 위에서 추상화 방식으로 동작되는 것이기에 설치 및 구성 편리
    • ex) Oracle Virtual Box

일반적으로 WSL2를 설치하여 Docker를 구동하기 위한 환경을 구축한다. WSL2(Windows Subsystem for Linux)는 경량화된 Barametal 하이퍼바이저이다. 

 

 

Docker 용어

Docker 격리 단위 : Docker Image

  • App + Bins/Libs (앱 구동 시 필요한 라이브러리, 실행파일, 환경변수)

Docker 격리 정의 : Dockerfile

  • 어떤 Bins/Libs와 어떤 App을 포장할지 = 이미지 생성 규칙

Docker 격리 동작 : Docker Container

  • 실행중인 이미지 = 컨테이너

Docker Compose

  • Dockerfile 두개를 엮어주는 설정 파일.
  • Docker Compose는 단일 인스턴스 내에서 다수 이미지에 대한 정의이다.
  • 주의 : 여러 도커 이미지를 엮어서(compose 해서) 하나의 도커 이미지를 만들 수는 없다.

Dockerfile, Docker Compose, Kubernetes 차이

  • Dockerfile : 1 호스트 내 1 단일 컨테이너 설정
  • Docker Compose:  1 호스트 내 N 다수 컨테이너 설정
  • Kubernetes : M 호스트 내 N 다수 컨테이너 설정
    • Orchestration : 다수의 컨테이너를 다수의 인스턴스에 지능적 배치

선언형 툴과 명령형 툴

  • Docker Compose, Dockerfile은 모두 선언형 툴이다. 
  • 선언 = What에 대한 정의 (상태성)
    • IaC(Infrastructure as Code)와 같은 곳에서 많이 활용
  • 명령 = How에 대한 정의 (절차성)
    • 일반적인 프로그래밍 언어

 

Docker Registry

  • Docker 이미지 중간 저장소
  • ex) Docker Hub, AWS ECR
  • Docker Image는 Docker Registry를 통해서만 저장, 다운이 가능하다. 

 

Docker Network

여러 개의 컨테이너를 함께 띄우는 경우 (Docker Compose), 컨테이너 간의 통신이 필요하다.

Docker Network는 NAPT(IP Masquerading)와 포트 포워딩을 기반으로 구성된다.

 

소프트웨어(Linux의 iptables) 기반의 가상 브릿지 혹은 L2 switch(docker 0) 중심으로

  • 내부 : 가상/물리 NIC 연결
  • 외부 : NAPT 혹은 IP masquerade 지원


NAT(Network Address Translation)

1개의 외부 IP 주소로 내부망 구성.
호스트 구별이 불가능하다. 따라서 Docker Network에서는 NAPT를 사용한다. 

NAPT(Network Address Port Translation)

1개의 외부 IP 주소 및 포트 번호로 내부망 구성. 호스트 구별

Port Forwarding

NAPT에서 포트 번호를 유동이 아닌 고정 포트를 사용함. (특정 외부 주소의 port로 들어온 요청은 특정 내부 주소의 port로만 향할 수 있도록 함.)

 


Docker Network 옵션 

1. Bridge 옵션

  • 하나의 호스트 컴퓨터 내에서 여러 컨테이너들이 서로 소통할 수 있도록 - 기본이자 많이 사용
  • 컨테이너와 호스트의 네트워크를 분리함.
  • 컨테이너와 호스트의 격리된 네트워크에 있기 때문에, 컨테이너의 포트와 호스트의 포트 번호가 같더라도 충돌하지 않는다.
  1. Default Bridge : 기본 제공 bridge
    • 어떠한 네트워크도 명시하지 않은 경우, Docker 기본 네트워크 구성은 Default Bridge
    • Docker0 : 자동 생성 bridge driver
  2. User-Defined Bridge : 사용자 정의 bridge
    • 소프트웨어(Linux의 iptables) 기반의 가상 브릿지
    • 컨테이너간 automatic DNS resolution을 제공한다. 

2. Host 옵션

  • 컨테이너를 호스트 컴퓨터와 동일한 네트워크에서 가동하기 위해서 사용 - 간단한 테스트용
  • 컨테이너와 호스트의 네트워크를 분리하지 않음.
  • network_mode : "host" 설정은 OSX에서 동작하지 않는 이슈가 있어 hostname을 지정하고 지정한 hostname으로 통신하는 방법이 제안된다.

 

CI / CD란?

CI (Continuous Integration) : 지속적 통합

  • Docker 이미지를 생성하고, Docker Registry에 Push.
  1. Java Application의 테스트 및 빌드
  2. Docker Image build 및 Docker Registry에 push.
    • 2-1. Build : Dockerfile을 정의하면, Docker가 이에 따라서 Docker Image를 생성한다.
    • 2-2. Push : 생성한 Docker Image를 Docker Registry에 업로드
    • 2-3. 테스트 자동화

CD (Continuous Deployment) : 지속적 배포

  • Docker Registry로부터 Docker 이미지를 Pull하고, Host에서 Docker Image 실행(= 배포)
  1. Pull : 호스트에서 Docker Registry로부터 Docker Image 다운로드
  2. Run : 호스트에서 앞서 다운로드 받은 Docker Image 실행 = Container


728x90