도커

정은영·2022년 11월 28일
0

CS

목록 보기
9/18

가상머신과 도커 컨테이너

가상머신

기존 가상화 기술은 하이퍼바이저를 이용해 여러 개의 운영체제를 하나의 호스트에서 생성해 사용하는 방식이다.

이러한 여러 개의 운영체제는 가상 머신이라는 단위로 구별되고, 각 가상머신에는 우분투, CentOS 등의 운영체제가 설치되어 사용된다.

이렇게 하이퍼바이저에 의해 생성되고 관리되는 운영체제는 게스트 운영체제(Guest OS)라고 하며. 각 게스트 운영체제는 다른 게스트 운영체제와는 완전히 독립된 공간과 시스템 자원을 할당 받아 사용한다.

ex) VirtualBox, VMware


가상 머신의 단점

  1. 각종 시스템 자원을 가상화하고 독립된 공간을 생성하는 작업은 하이퍼바이저를 반드시 거치기 때문에 일반 호스트에 비해 성능의 손실이 발생한다.

  2. 가상 머신은 게스트 운영체제를 사용하기 위한 라이브러리, 커널 등을 전부 포함하기 때문에 가상 머신을 배포하기 위한 이미지로 만들었을 때 이미지의 크기가 커진다.

    수 기가바이트에 달하는 가상 머신 이미지를 애플리케이션으로 배포하기는 부담스럽다.


가상 머신의 장점

  1. 완벽한 운영체제를 생성할 수 있다.
  2. 보안적인 측면에서 유리하다.
  • 아래에서 나올 container는 host의 커널을 공유하는데 host의 커널을 공유한다는 것은 container 하나가 뚫리면 바로 host 커널이 위험해진다는 것을 뜻한다. 반면 vm은 하나의 vm이 공격당해도 거의 완벽하게 다른 vm이나 host가 보호된다.
  1. 멀티 OS
    • 커널을 공유한다는 내용 때문에 container는 호스트 os와 전혀 다른 os를 container로 올릴 수 없다. linux 머신에서 window 서버를 container로 올릴 수 없다는 뜻이다. 반면 vm은 하드웨어 가상화를 통해 완벽히 가상화된 os를 올릴 수 있기 때문에 os 선택에서 자유롭다.



도커 컨테이너

도커 컨테이너는 가상화된 공간을 생성하기 위해 리눅스 자체 기능인 chroot, 네임스페이스(namespace), cgroup을 사용함으로써 프로세스 단위의 격리 환경을 만들기 때문에 성능 손실이 거의 없다.

컨테이너에 필요한 커널은 호스트의 커널을 공유해 사용하고, 컨테이너 안에는 애플리케이션을 구동하는데 필요한 라이브러리 및 실행 파일만 존재하기 때문에 컨테이너를 이미지로 만들었을 때 이미지의 용량 또한 가상머신에 비해 대폭 줄어든다. 따라서 컨테이너를 이미지로 만들어 배포하는 시간이 가상 머신에 비해 빠르다.



도커 컨테이너의 장점

  1. 애플리케이션의 개발과 배포가 편해진다.

    • 컨테이너를 운영 환경에 배포할 때 해당 컨테이너를 '도커 이미지'라고 하는 일종의 패키지로 만들어 운영 서버에 전달하기만 하면 된다. 운영 서버에서 새롭게 패키지를 설치할 필요도 없고, 각종 라이브러리 설치 등으로 인한 의존성을 걱정할 필요도 없다.

    • 서비스를 개발했을 대 사용했던 환경을 다른 서버에서도 컨테이너로 똑같이 복제할 수 있기 때문에 개발/운영 환경의 통합이 가능해진다.


    • 도커 이미지는 가상 머신의 이미지와 달리 커널을 포함하고 있지 않기 때문에 이미지 크기가 그다지 크지 않다.

    • 도커는 이미지 내용을 레이어 단위로 구성하며 중복되는 레이어를 재사용할 수 있어서 애플리케이션의 배포 속도가 매우 빨라진다.


  2. 여러 애플리케이션의 독립성과 확장성이 높아진다.

  • 컨테이너는 마이크로 서비스 구조에서 가장 많이 사용되고 있는 가상화 기술이다.
  • 마이크로서비스 구조는 여러 모듈을 독립된 형태로 구성하기 때문에 언어에 종속되지 않고 변화에 빠르게 대응할 수 있으며, 각 모듈의 관리가 쉬워진다는 장점이 있다.
  • 컨테이너는 수 초 내로 생성, 시작이 가능할 뿐만 아니라 여러 모듈에게 독립된 환경을 동시에 제공할 수 있기 때문에 마이크로서비스 구조에서 가장 많이 사용되고 있다.
  • 예를 들어 웹 서비스는 데이터베이스 컨테이너와 웹 서버 컨테이너로 분리할 수 있고, 웹 서비스에서 부하가 발생할 시 마이크로서비스 구조의 웹 서버 컨테이너만을 동적으로 늘려서 부하를 분산할 수 있다. 또한 웹서버와 데이터베이스의 이미지 버전을 독립적으로 관리하기 때문에 유지 보수도 용이해진다.



도커 이미지와 컨테이너


도커 이미지

이미지는 컨테이너를 생성할 때 필요한 요소이다.


도커 컨테이너

도커 이미지는 우분투, CentOS 등 기본적인 리눅스 운영체제부터 아파치 웹 서버, MySQL 데이터베이스 등의 각종 애플리케이션, 하둡(Hadoop)이나 스파크(Spart), 스톰(Storm) 등의 빅데이터 분석 도구까지 여러 종류가 있다.

이러한 이미지로 컨테이너를 생성하면 해당 이미지의 목적에 맞는 파일들이 들어 있는 파일시스템과 격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립된 공간이 생성되고 이것이 바로 도커 컨테이너이다.

ex) 웹 서버 도커 이미지로부터 여러 개의 컨테이너를 생성하면 생성된 컨테이너의 개수만큼 웹 서버가 생성되고, 이 컨테이너들은 외부에 웹 서비스를 제공하는데 사용된다.


도커 컨테이너와 이미지는 1:N 관계이다.

컨테이너는 이미지를 읽기 전용으로 사용하며 이미지에서 변경된 사항만 컨테이너 계층에 저장하므로 컨테이너에서 무엇을 하든지 원래 이미지는 영향을 받지 않는다.

또한 생성된 각 컨테이너는 각기 독립된 파일시스템을 제공받으며 호스트와 분리돼 있으므로 특정 컨테이너에서 어떤 애플리케이션을 설치하거나 삭제해도 다른 컨테이너와 호스트는 변화가 없다.

ex) 우분투 도커 이미지로 두 개의 컨테이너를 생성한 뒤 A 컨테이너에 MySQL을, B 컨테이너에 아파치 웹 서버를 설치해도 각 컨테이너는 서로 영향을 주지 않을뿐더러 호스트에도 아무런 영향을 주지 않는다.




도커 볼륨


도커 이미지로 컨테이너를 생성하면 이미지는 읽기 전용이 되며 컨테이너의 변경 사항만 별도로 저장해서 각 컨테이너의 정보를 보존한다.

이미지에 mysql을 실행하는 데 필요한 애플리케이션 파일이 들어있다면 컨테이너 계층에는 프로그램에서 쓴 로그인 정보나 게시글 등과 같이 데이터베이스를 운용하면서 쌓이는 데이터가 저장된다.


하지만 이러한 구조에는 문제점이 있다. mysql 컨테이너를 삭제하면 컨테이너 계층에 저장돼있던 데이터베이스의 정보도 삭제된다. 이를 방지하기 위해 컨테이너의 데이터를 영속적 데이터로 활용할 수 있는 방법이 있다. 볼륨을 활용하는 것이다. 볼륨을 활용하는 방법으로는 세가지 방법이 있다.


1. 호스트 볼륨 공유

호스트와 볼륨을 공유함으로써 데이터베이스 컨테이너를 삭제해도 데이터는 삭제되지 않도록 설정할 수 있다.


2. 볼륨 컨테이너

볼륨 컨테이너는 데이터를 저장하는 것만이 목적인 컨테이너이다. 호스트-컨테이너 볼륨은 호스트 쪽 특정 디렉터리에 의존성을 갖는다. 데이터 볼륨 컨테이너의 볼륨은 도커에서 관리하는 영역인 호스트 머신의 /var/lib/docker/volumes/ 아래에 위치한다. 데이터 볼륨 컨테이너 방식은 도커가 관리하는 디렉터리에만 영향을 미친다. 호스트-컨테이너 데이터 볼륨과 비교하면 호스트 머신이 컨테이너에 미치는 영향을 최소한으로 억제한다. 또 데이터 볼륨 컨테이너가 직접 볼륨을 다뤄주므로 볼륨을 필요로 하는 컨테이너가 사용할 호스트 디렉터리를 알 필요가 없고, 디렉터리를 제공하는 데이터 볼륨 컨테이너만 지정하면 된다.


3. 도커 볼륨

도커 자체에서 제공하는 볼륨 기능을 활용해 데이터를 보존할 수 있다. 볼륨을 생성할 때 여러 종류의 스토리지 백엔드를 쓸 수 있지만 기본적으로 제공되는 드라이버인 local을 사용하게 되면 볼륨은 로컬 호스트에 저장되며 도커 엔진에 의해 생성되고 삭제된다.

도커 볼륨도 호스트 볼륨 공유와 마찬가지로 호스트에 저장함으로써 데이터를 보존하지만 파일이 실제로 어디에 저장되는지 사용자는 알 필요가 없다.




도커 컴포즈

도커 컴포즈를 사용하는 이유

여러 개의 컨테이너가 하나의 애플리케이션으로 동작할 때 이를 테스트하려면 각 컨테이너를 하나씩 생성해야 한다.
→ 즉, run 명령어를 여러번 사용해야 한다.


매번 run 명령어에 옵션을 설정해 cli로 컨테이너를 생성하기 보다는 여러 개의 컨테이너를 하나의 서비스로 정의해 컨테이너 묶으로 관리할 수 있다면 좀 더 편리할 것이다.


이를 위해 도커 컴포즈는 컨테이너를 이용한 서비스의 개발과 CI를 위해 여러 개의 컨테이너를 하나의 프로젝트로서 다룰 수 있는 작업환경을 제공한다. 컨테이너의 수가 많아지고 정의해야 할 옵션이 많아진다면 도커 컴포즈를 사용하는 것이 좋다.


도커 컴포즈는 여러 개의 컨테이너의 옵션과 환경을 정의한 파일을 읽어 컨테이너를 순차적으로 생성하는 방식으로 동작한다. 도커 컴포즈의 설정 파일은 run 명령어의 옵션을 그대로 사용할 수 있으며, 각 컨테이너의 의존성, 네트워크, 볼륨 등을 함께 정의할 수 있다.
도커 컴포즈는 컨테이너의 설정이 정의된 YAML 파일을 읽어 도커 엔즌을 통해 컨테이너를 생성한다. 따라서 도커 컴포즈를 사용하려면 YAML 파일을 작성해야 한다.


YAML 파일 작성법

YAML 파일은 크게 버전 정의, 서비스 정의, 볼륨 정의, 네트워크 정의 4가지 항목으로 구성된다.
(각 항목의 하위 항목을 정의하려면 2개의 공백으로 들여쓰기 해서 상위 항목과 구분한다.)

docker-compose.yml
#https://docs.docker.com/compose/compose-file/compose-file-v3/ 에서 버전 확인 가능

version: '3'
services:
 #항목명 = 서비스명 = 네트워크 호스트명
 database:
   # Dockerfile이 있는 위치
   build: ./database
   # 내부에서 개방할 포트 : 외부에서 접근할 포트
   ports:
     - "3306:3306"
 #항목명 = 서비스명 = 네트워크 호스트명
 backend:
   build: ./backend
   # 연결할 외부 디렉토리 : 컨테이너 내 디렉토리
   volumes:
     - ./backend:/usr/src/app
   ports:
     - "5000:5000"
   # 환경변수 설정
   environment: 
     - DBHOST=database
 #항목명 = 서비스명  = 네트워크 호스트명
 frontend:
   build: ./frontend
   # 연결할 외부 디렉토리 : 컨테이너 내 디렉토리
   volumes:
     - ./frontend:/home/node/app
   ports:
     - "8080:8080"​
     

(1) 버전 정의

version: '3'

(2) 서비스 정의

서비스는 도커 컴포즈로 생성할 컨테이너 옵션을 정의한다.
이 항목에 쓰인 각 서비스는 컨테이너로 구현되며, 하나의 프로젝트로서 도커 컴포즈에 의해 관리된다.
서비스의 이름은 services의 하위 항목으로 정의하고 컨테이너의 옵션은 서비스 이름의 하위 항목에 정의된다.

  • image: 서비스의 컨테이너를 생성할 때 쓰일 이미지의 이름을 설정한다.
  • links: docker run 명령어의 --link와 같으며, 다른 서비스에 서비스명만으로 접근할 수 있도록 설정한다.
  • environment: docker run 명령어의 --env, -e 옵션과 동일하다. 서비스의 컨테이너 내부에서 사용할 환경변수를 설정하며, 딕셔너리나 배열 형태로 사용할 수 있다.
  • command: 컨테이너가 실행될 때 수행할 명령어를 설정한다.
  • depends_on: 특정 컨테이너에 대한 의존 관계를 나타내며, 이 항목에 명시된 컨테이너가 먼저 생성되고 실행된다.
  • ports: docker run 명령어의 -p와 같으며 서비스의 컨테이너를 개방할 포트를 설정한다.
  • build: build 항목에 정의된 Dockerfile에서 이미지를 빌드해 서비스의 컨테이너를 생성하도록 설정한다.
    ex) ./backend 디렉터리에 저장된 Dcokerfile로 이미지를 빌드해 컨테이너를 생성한다.
backend:
   build: ./backend
  • extends: 다른 YAML 파일이나 현재 YAML 파일에서 서비스 속성을 상속받게 설정한다.

(3) 네트워크 정의
(4) 볼륨 정의



REFERENCE

  • 책, 시작하세요! 도커/쿠버네티스 - 친절한 설명으로 쉽게 이해하는 컨테이너 관리

0개의 댓글