Docker
데이터 엔지니어가 알아야하는 Docker
회사에서 일하면서 Docker를 이용해서 가상서버를 띄워야하는 일을 맡게 되었다. Docker Compose를 사용하여 서버를 띄웠는데 사실상 개념적으로 내가 부족한 부분이 많이 Docker에 대해 정리해보기로 했다.
Docker란?
-
Docker는 오픈 소스 컨테이너화 플랫폼이다. 이를 통해 개발자는 애플리케이션을 컨테이너로 패키징할 수 있다. 컨테이너랑 애플리케이션 소스 코드를 임의의 환경에서 해당 코드의 실행에 필요한 운영체제(OS) 라이브러리 및 종속 항목과 결합하는 실행 가능한 표준 컴포넌트를 말한다. 컨테이너는 분산형 애플리케이션의 딜리버리를 간소화하며, 이는 기업들이 클라우드 네이티브 개발 및 하이브리드 멀티클라우드 환경으로 이전하면서 점점 더 유명세를 타고 있다.
-
개발자는 Docker를 사용하지 않고도 컨테이너를 구축할 수 있지만, Docker 플랫폼을 이용하면 보다 손쉽고 보다 간편하며 보다 안전하게 컨테이너를 빌드, 배치 및 관리할 수 있다. Docker는 기본적으로 개발자가 단일 API를 통한 업무 절감 자동화와 간단한 명령을 사용하여 컨테이너를 빌드, 배치, 실행, 업데이트 및 중지할 수 있도록 해주는 툴킷이다.
-
리눅스 컨테이너(Linux Container)기술을 기반으로하는 오픈소스 서비스이며 이를 통해 애플리케이션 실행 환경을 코드로 작성할 수 있으며 OS를 공유,격리화하여 관리할 수 있다.
-
Docker는 컨테이너 기술을 사용하여 애플리케이션에 필요한 환경을 신속하게 구축하고 테스트 및 배포를 할 수 있게 해주는 플랫폼으로 Linux(Ubuntu,CentOS,Debian),Cloud(Azure,AWS),windows10,MacOS 등에서 작동 가능하다.
-
MSA(Micro Service Architecture)가 대세로 떠오르면서 MSA의 단점인 관리의 복잡성을 해결해주기 위해 서비스의 컨테이너화가 이루어지고, 이 과정에서 Docker와 Kubernetes가 많이 도입되었다.
-
MSA란?
###### MSA는 서비스간의 의존성을 없애고 기능을 쪼개는 것을 중점적으로 설계한 아키텍쳐이다. 예를 들어, 은행 시스템을 하나의 통합된 프로그램으로 개발하지 않고 입/출금 서비스, 조회 서비스,대출 서비스 등 기능별로 작게 쪼개서 MSA 형태로 되어있다고 가정해보자.
###### 이 때 새로운 대출 유형이 생겨 개발이 필요하면 은행 시스템 전체를 수정할 필요없이 대출 서비스의 수정만으로 작업을 경량화 할 수 있다.
###### 위의 예시처럼 MSA는 아래와 같은 장점이 있다. - 서비스 단위의 개발가능 - 지속적인 통합과 배포(CI/CD)를 효율적으로 할 수 있음 - 패치가 필요한 서비스만 배포하거나 Hotfix를 빠르게 처리할 수 있다. - 전체가 아닌 필요한 서비스에만 이중화 할 수 있다. ###### 전체적인 그림에서 서비스 간 결합도(Coupling)를 줄이고 응집도(Cohesion)를 높이는 효과를 볼 수 있다. 그러나 서비스들을 관리하기 복잡하다는 단점이 있는데 이는 Docker를 사용하면 이런 문제를 쉽게 해결할 수 있다.
-
Linux Container란?
-
Linux 기반의 기술 중 하나로 필요한 라이브러리와 애플리케이션을 모아서 마치 별도의 서버처럼 구성한 것을 말한다. 리눅스 컨테이너는 컨테이너를 이루는 네트워크 설정,환경변수 등의 시스템 자원은 각 컨테이너가 독립적으로 소유하고 있다.
- 프로세스의 구획화
-
특정 컨테이너에서 작동하는 프로세스는 기본적으로 그 컨테이너 아에서만 액세스 할 수 있다.
-
컨테이너 안에서 실행되는 프로세스는 다른 컨테이너의 프로세스에게 영향을 줄 수 없다.
-
- 네트워크의 구획화
-
기본으로 컨테이너 하나에 IP주소가 할당되어 있다.
-
하나의 컴퓨터가 하나의 Ip주소를 갖는 것을 극복한다.
-
- 파일 시스템의 구획화
-
컨테이너 안에서 사용되는 파일 시스템은 구획화되어 있으며 이로 인해 해당 컨테이너에서의 명령이나 파일 등의 액세스를 제한할 수 있다.
-
- 컨테이너가 공유/격리 하는 것
-
공유하는 것
-
CPU 성능(하드웨어)
-
메모리(하드웨어)
-
리눅스 커널(Host OS)
-
-
격리하는 것
-
네트워크(IP,PORT)
-
파일
-
프로세스
-
-
- 컨테이너 기술로 Docker가 갖는 장점
-
환경 표준화를 통한 생산성 향상
-
엔지니어는 자신이 개발하는 애플리케이션이 어떤 환경에서 구동될지 생각하고 개발해야한다. 그리고 개발하려고 하는 여러 애플리케이션을 구동하는 운영체제가 서로 다르다면 환경에 따라 조금씩 변경할 부분이 발생한다. (예를 들어, 윈도우에서 개발한 애플리케이션에서의 경로는 Back slash(‘')를 폴더로 표현하고, Mac이나 Linux에서 경로는 slash(‘/’)를 폴더로 표현한다.) 환경이 다르다면 개발자들이 조정할 무제가 수도 없이 생기며, 수작업으로 환경을 맞추는 것은 쉬운 일이 아니다. 하지만 Docker의 등장으로 인해 환경까지 Packaging 햐야하기 떄문에 생산성이 향상된다.
-
-
환경 구성 코드 제공을 통한 생산성 향상
-
개발된 애플리케이션을 내 컴퓨터에 설치해 사용하고자 할 때, ‘내 컴퓨터’ 혹은 ‘내 사용목적’에만 맞는 설정이 따로 필요할 수 있다.(예를 들어, 환경변수처럼 동일 OS일지라도 사용자에 따라 달라지는 구성이 있다. echo $HOME 코드를 로컬 터미널(CLI)의 프롬프트에 입력해보면 컴퓨터 마다 다르다.) 이처럼 홈 디렉초리가 다르듯 애플리케이션을 설치할 때, 컴퓨터의 환경에 맞게 변경해야하는 부분이 있다(방화벽 설정, 사용자권한 설정, Port 설정 등). 이런 다양한 설정작업을 수작업으로 하게 된다면 많은 시간이 걸릴 뿐만 아니라 설정 간에 간섭이 일어나 프로그램이 멈출 수 도 있다. 하지만 개발과 실행에 대한 환경 설정이 코드로 정해져있다면, 이런 고민으로부터 벗어날 수 있다.
-
-
리소스 격리성을 통한 응용 프로그램 + 실행 환경 분리
-
리소스 격리성이란 실제로는 하나의 컴퓨터를 사용하지만, 여러 개의 컴퓨터를 이용하는 것처럼 IP와 PORT등을 다르게 설정하는 방법을 말하는데 이런 리소스 격리성을 제공하는 기술로는 가상머신(Virtual Machine)과 Docker 등이 있다. OS도 일치시키고 환경도 일치시키기 위해 가상 머신을 이용하는 것도 좋은 방법이다. 그러나 둘에는 차이점이 있는데 컨테이너 기술은 애플리케이션이 격리할 수 있게 만드는 기술 이고 격리는 응용 프로그램 + 실행 환경을 각각 분리하는 것이다.
-
-
가상화 기술과 컨테이너 기술의 차이
Legacy
-
하나의 물리서버에 애플리케이션 배포
-
애플리케이션간 라이브러리나 미들웨어 버전의 충돌이 발생할 수 있음
Hoseted Hypervisor(가상화 소프트웨어)
-
Virtual Box, VMWare, Parallels와 같은 소프트웨어
-
Host OS위에 가상화 소프트웨어를 설치해서 가상환경 구축
-
간편하게 사용할 수 있어 클라이언트 PC에서 개발환경을 구축하거나 테스트를 위해 주로 사용
-
컨테이너와는 다르게 Guest OS가 존재하며 오버헤드가 비교적 크다.
-
OS 위에 OS를 실핼하는 것이므로 리소스(CPU,메모리 등)를 할당하는데 작업이 필요
-
Bare Metal Hypervisor
-
Hyper-v,XenServer, ESXI Server 등이 있다.
-
Host OS 없이 하드웨어에 직접 하이퍼바이저를 설치
-
Host OS가 없어 자원을 효율적으로 사용할 수 있다.
-
하드웨어가 제어
-
오버헤드가 비교적 적다.
-
-
가상 머신들을 관리하기 위한 콘솔이 필요
Container
-
Docker,containerd,CRI-O 등이 컨테이너 런타임으로 있음
-
Guest OS가 없고 Host OS의 커널을 공유하여 오버헤드가 적고 가벼워 빠르다.
-
OS 실행 없이 별도의 환경에서 애플리케이션 실행이 가능
-
-
이식성과 확장성이 높다.
▷ 가상화 기술과 컨테이너 기술은 비슷하면서도 다르다. 어느 하나가 더 좋다 나쁘다라고 정의하기보다는 각각 목적에 맞게 다르게 사용되고 있다.
Docker Image
-
컨테이너를 생성하는 Base가 되는 것이 이미지이다. 이미지는 컨테이너를 실행하는데 필요한 모든 것을 포함하고 재사용이 가능하다. 붕어빵 틀과 붕어빵으로 생각하면 쉽게 접근할 수 있다.
-
단순히 개발하고 있는 애플리케이션만 이미지 형태로 만들어서 배포하는 것이 아니라, Database나 web/was 처럼 미들웨어로 사용되는 프로그램들 혹은 다른 OS환경을 실행하기 위한 이미지가 Docker이미지 Repository(docker hub)에 배포되어 있어 받아서 사용하면 된다.
EX
- Oracle 이미지를 받아서 컨테이너를 생성하고 DB로 활용
- Java,Apache/Tomcat이 설치되어 있는 이미지를 받아서 그 위에 애플리케이션을 올리고 재배포
- Windows OS에서 CentOS 운영체제를 사용하기 위해 CentOS이미지를 받아서 사용
Docker Compose
Docker compose란?
-
복수 개의 컨테이너를 실행시키는 Docker 애플리케이션을 정의하기위한 Tool 이다.
-
여러개의 컨테이너로부터 이루어진 서비스를 구축, 실행하는 순서를 자동으로 하여 관리를 간단하게 하는 것으로, 여러개의 컨테이너 설정 내용을 하나의 yaml 파일에 모아서 사용한다. compose 파일을 준비해서 커맨드를 1번 실행하는 것 만으로 그 파일로부터 설정을 읽어들여 모든 컨테이너 서비스를 실행시킬 수 있다.
Docker-compose 사용 방법
-
각각의 컨테이너의 Dockerfile을 작성한다.
-
docker-compose.yml을 작성하고, 각각 독립된 컨테이너의 실행 정의를 실시한다.
-
docker-compose up 커맨드를 실행해서 docker-compose.yml으로 정의한 컨테이너를 개시한다.
Docker-compose.yml 파일
version: '3.5'
services:
mockserver:
build: mockserver
# mockerserver 폴더 안에 사용할 Dockerfile이 있음
ports: ['8001:8000']
# 호스트 OS 8001 <= mockserver 컨테이너 포트 8000
volumes:
- './mockserver/public:/home/public'
- './mockserver/server.py:/home/server.py'
web:
build:
context: .
dockerfile: web/Dockerfile
# web 폴더 안에 사용할 Dockerfile이 있음
cache_from:
- eu.gcr.io/tmrow-152415/electricitymap_web:production
- eu.gcr.io/tmrow-152415/electricitymap_web:staging
- eu.gcr.io/tmrow-152415/electricitymap_web:latest
image: eu.gcr.io/tmrow-152415/electricitymap_web:latest
# 베이스 이미지
command: npm run server-dev
# 이 서비스가 올라올 때 dockerfile의 CMD를 무시하고 npm run server-dev가 실행됨
depends_on: ['mockserver']
# web이 올라오기 전에 mockserver가 먼저 올라와야 함
environment:
- NODE_ENV=development
ports: ['8000:8000']
# 호스트 OS 8000 <= web 컨테이너 포트 8000
volumes:
- './config:/home/config'
- build
-
해당 서비스의 이미지를 빌드하기 위한 Dockerfile이 위치하는 경로를 저장한다.
-
- ports
-
Host OS와 컨테이의 포트를 바인딩 시켜준다. 따옴표와 함꼐 문자열로 지정해야한다.
-
형식은 “host:container” 또는 “container”
-
외부로 노출시킬 포트의 매핑을 명시하는 부분이다.
-
bind가 필요한 호스트 외부 포트와 컨테이너 내부 포트를 지정
-
- image
-
docker-compose 안에서 베이스 이미지를 지정한다.
-
- command
-
해당 서비스가 올라올때 Dockerfile의 CMD 명령문을 무시하고 실행할 명령어를 설정한다.
-
- depends-on
-
서비스 간의 종속성 순서대로 서비스를 시작한다.
-
A: depends_on: -B : A 애플리케이션이 올라오기 전에 B가 먼저 올라와야 한다.
-
- environment
-
컨테이너 환경 변수를 지정한다.
-
Dockerfile
FROM python:3.8-alpine
WORKDIR /home
EXPOSE 8000
ADD server.py server.py
CMD cd public && python ../server.py
- EXPOSE
-
Host OS에 포트를 공개하지 않고,컨테이너에서만 포트를 공개한다.
-
- ADD
-
파일을 이미지에 추가한다.
-
- CMD
-
컨테이너가 시작되었을 때 스크립트 혹은 명령을 실행한다.
-
그 외 개발에 도움이 되었던 글