Docker for MLOps

Eunsoo Max EunEunsoo Max Eun
4 min read

이번에는 MLOps 입문을 위해 빠르고 간단한 도커 관련 개념 글 하나로 정리하기...같은 개념으로 작성해봤다. 어차피 이미 도커 관련 글이 블로그에 있으니...

Why Docker container?

ML 프로젝트들을 하다보면 특정 라이브러리에 의존하게 되는 경우가 많은데, 배포하려는 경우 환경도 라이브러리 버전, 운영체제 및 기타 환경들을 똑같이 맞춰주지 않으면 프로그램이 정상적으로 동작하지 않는다. 이러한 문제점을 해결하기 위해 가상머신들을 쓰곤 했고 아직도 가상머신이 많이 쓰이고 있다.

그러나 가상머신도 문제점들이 존재하는데...그러나 공통적으로는 가상머신이 너무 무겁기 때문에 일어나는 일들이다. 가상머신은 무겁기 때문에

  1. 옮기기 어렵고

  2. 그 자체로 리소스의 낭비가 있다고 볼 수 있다.

환경 분리를 하면서도 이것을 더 가볍게 쓰기 위해 나온 기술이 도커 컨테이너라고 할 수 있겠다.

도커에서 사용하는 컨테이너라는 개념은 실제 컨테이너와 거의 유사하다. 다만 물건이 아니라 애플리케이션을 담고 있을 뿐이다. 그런데 이 컨테이너 안에는 실제 컴퓨터처럼 호스트명, IP 주소, 디스크 드라이브도 들어있고 호스트 머신의 것들과 다르다.

이건 도커가 호스트명과 IP 주소, 파일 시스템까지 가상 리소스를 만들어 컨테이너에 넣어두었기 때문이다.

Container vs VM

컨테이너와 가상 머신의 차이점은 간단하다. 가상 머신은 호스트 머신의 운영체제를 공유하지 않고 별도의 운영체제를 필요로 한다. 그러나 컨테이너는 호스트 머신의 운영체제를 사용한다.

예를 들어 가상머신 A와 B가 있다고 할 때 A와 B는 별도의 운영체제를 필요로 하기 때문에 호스트 머신까지 합해 운영체제가 총 3개 필요하다.

그러나 컨테이너는 호스트 머신의 운영체제만으로 충분하다.(적어도 리눅스 머신에서는)

운영체제는 그 자체로 무거운 프로그램이다. 운영체제가 중복 설치된다는 점이 리소스 측면에서는 전혀 바람직한 상황은 아니다. 컨테이너는 서로 다른 호스트명 IP주소 디스크 드라이브를 가지는 환경들을 생성하면서도 운영체제는 공유하는 방식을 사용한다. 따라서 필요한 리소스가 확연하게 줄어들게 된다.

그래서 컨테이너는 실행도 빠르고 같은 호스트 컴퓨터에도 가상머신보다 더 많은 수를 올릴 수 있다. 일반적으로 5배 더 많이 올릴 수 있다고 한다. 리소스에서 운영체제가 차지하는 비율이 높을수록 수가 더 차이날 것으로 볼 수 있다.


Docker Image vs Docker container

도커 (Docker)

실제로 애플리케이션이 구동되는 공간은 컨테이너이고, 이미지는 컨테이너를 찍어내기 위한 틀이다.

이 둘의 관계는 클래스-인스턴스와도 꽤나 비슷하다. 클래스는 인스턴스를 찍어낼 수 있지만 인스턴스를 생성하지 않고서는 그 자체로 기능을 수행하는 것은 아니다.

마찬가지로 이미지로 컨테이너들을 찍어낼 수 있지만 이미지만으로는 애플리케이션을 돌릴 수 없다.

이미지는 그야말로 컨테이너를 찍어내기 위한 틀이기 때문에 공유가 가능하다. 이런 공유는 도커 허브에서 이루어진다.

아래에서 조금 더 설명하겠지만 실제로 구조가 틀로 무언가를 찍어내는 그런 느낌은 사실 아니기는 하다....

도커 이미지 좀 더 알아보기

이미지의 구조

도커 이미지는 레이어로 구성된다. 도커는 매번 명령을 캐싱해두었다가 이미지를 다시 빌드할 때 캐싱된 결과를 가져와서 사용한다.

이미지를 빌드할 때 도커는 명령문들을 실행하면서 데이터를 독립적으로 저장하게 되는데, 이 저장된 데이터들이 레이어이다. 이런 환경 정보에 대한 레이어들은 읽기 전용이라 임의로 변경할 수 없다.

그리고 도커 컨테이너가 실행되면 읽기 전용 레이어들을 순서대로 쌓은 다음 마지막에 쓰기 가능한 레이어를 추가하는데, 컨테이너에서 발생한 일들은 이 쓰기 가능한 마지막 레이어에 기록되게 된다.

그림으로는 이러한 식인 것이다.

도커파일 더 효율적으로 작성하기

도커 이미지가 레이어로 저장된다는 것을 알아야 하는 이유가 있는데

한줄요약하자면 도커가 레이어인지 뭔지 그런 걸 가지고 있어서 데이터가 캐싱되니까 매번 명령을 처음부터 실행하는 것이 아니라는 건데, 이걸 알면 도커파일을 더 효율적으로 작성할 수 있다는 거다.

예를 들자면 js앱을 만들고 있는데 app/ 디렉토리의 코드에 뭔갈 변경했기 때문에 이미지를 다시 빌드하고자 하는 상황이다. 그런데 도커파일이

FROM node

WORKDIR /app

COPY . /app

RUN npm install

EXPOSE 80

CMD ["node", "server.js"]

이렇게 되어있다고 에러가 나거나 큰 일이 벌어지는 건 아니지만 의존성에 변화가 없다면 COPY . /app부터 코드의 변화로 변경사항이 생기게 되는데 이러면 의존성을 다시 설치하느라 느리다.

FROM node

WORKDIR /app

COPY package.json /app

RUN npm install

COPY . /app

EXPOSE 80

CMD ["node", "server.js"]

그러니까 이렇게 짜는 것이 더 낫다는 것이다. 의존성은 상대적으로 변화 가능성이 적고 설치 자체도 매우 오래걸리므로 코드 카피를 뒤에 두고, 의존성은 캐싱된 결과 쓰자는 것이다. 그러면 대체로 더 효율적으로 만들 수 있다.


도커 명령어

명령어는....일단 이 글에서는 자세하게 다룰 마음이 없다. 일단 help치면 다 나오기도 하고...어차피 구글링의 영역이니. 도커를 공부하면서도 매번 잊어먹기 때문에 항상 찾아보고 있다. 이것은 잘 정리된 블로그를 참고하길 바란다.

내 블로그로 말하자면 https://maximizemaxwell.com/docker-images-container#heading-14 를 참고하길 바란다...


도커 컴포즈

도커 컴포즈는 여러 개의 컨테이너로 구성된 애플리케이션을 단일 도커 엔진 호스트에서 실행하기 위한 도구이다.

여러 개의 컨테이너를 굴리다보면 이걸 명령어를 일일히 쳐서 하기가 상당히 번거로운데, 명령어에 붙는 그런 부가적인 옵션을 한 파일에 몰아넣은 녀석을 docker-compose.yaml라고 하는 것이다.

도커 컴포즈 파일 설계하기

오버라이드 파일을 이용한 도커 컴포즈 설계에 대해 소개하는 내용을 조금 갖고 왔다.

여러 가지 설정으로 애플리케이션을 실행하고 싶을 수 있는데 대부분의 경우 컴포즈 파일을 여러 개 둔다고 한다. 그런데 컴포즈 파일을 각각 작성하게 된다면 대부분의 내용이 사실상 중복인데, 수정 시 이 부분이 누락된다거나 하면 문제가 생기므로 유지 보수 측면에서 좋지 않다고 하는 것이다.

도커 컴포즈는 여러 파일을 합쳐 컴포즈 파일을 구성할 수 있는데, 나중에 지정된 파일의 내용이 이전 파일의 내용을 덮어쓰기(오버라이드)한다.

그렇다면

  • docker-compose.yaml: services(기본 컴포즈 파일. 공통적 정의)

  • docker-compose-dev.yaml: services, networks(개발 환경용)

  • docker-compose-test.yaml: services, networks, volumes(테스트용)

  • docker-compose-uat.yaml: 사용자 인수 테스트 대상

해당 파일에 각각 기능에 필요한 것만 추가하고

docker container rm -f $(docker container ls -aq)

docker-compose -f ./numbers/docker-compose.yml -f ./numbers/docker-compose-dev.yml -p numbers-dev up -d
//개발 환경용

docker-compose -f ./numbers/docker-compose.yml -f ./numbers/docker-compose-test.yml -p numbers-test up -d
//테스트 환경용

docker-compose -f ./numbers/docker-compose.yml -f ./numbers/docker-compose-uat.yml -p numbers-uat up -d
//인수 테스트 환경용

이런 식으로 각각의 환경을 만들 수 있겠다는 내용이다.

0
Subscribe to my newsletter

Read articles from Eunsoo Max Eun directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Eunsoo Max Eun
Eunsoo Max Eun