컨테이너 이미지 용량을 줄이기 위한 방법을 소개합니다.
많은 고객들이 Dockerfile을 작성할 때 의도한 것과 다르게 작성하여 이미지 사이즈를 크게 사용하고 있는 경우가 많습니다. Dockerfile을 잘 작성하여 컨테이너 이미지 사이즈를 줄이는 방법에 대해 정리해 보겠습니다.
우선 흔히 발생하는 Dockerfile 작성의 아쉬운 점을 해결해 보겠습니다.
아래 링크 게시물 중 이미지 레이어 부분을 주의 깊게 읽어보시면 도움이 됩니다.
도커와 컨테이너의 이해(3/3) (링크수정 필요)
이야기 하고자 하는 내용과 관련 있는 중요한 내용을 발췌 하면 다음과 같습니다.
즉, 명령어를 실행하는 순서 자체가 중요하다는 것이고, 이 명령어 순서에 따라서 실제로 컨테이너가 생성되는 구조가 달라지는 것입니다.
다음의 Dockerfile은 머신러닝용 컨테이너를 작성할 때 자주 사용하는 형태를 최소화 한 형태입니다.
FROM pytorch/pytorch:latest
ENV PYTHONUNBUFFERED 1
COPY source/ /app/source/
RUN pip install –-upgrade pip
RUN pip install -r \
/app/source/requirements.txt
CMD python /app/source/app.py
위와 같은 Dockerfile을 통해서 컨테이너 이미지를 작성한 경우, 생성되는 이미지 레이어의 구조 및 사이즈를 살펴보겠습니다.

'이 구조에 문제가 있는가?'라고 한다면 아무런 문제가 없습니다. 그렇다고 '개선할 부분은 없는가?'라고 물어본다면 '개선할 부분이 존재한다' 라고 할 수 있습니다.
대부분의 개발 과정을 보면 요즘은 DevOps의 도식으로 설명이 가능합니다.

개발하고 확인하고 수정하고 또 확인하고 이 과정의 연속이며, 이 과정에서 우리는 수 없이 이미지를 생성하고 컨테이너를 사용합니다.
그렇다면 코드를 변경한 뒤 새롭게 변경되는 이미지 레이어 중 새롭게 생성된 레이어의 내용을 확인해 보겠습니다. 다음의 이미지는 소스 코드에 포함되어 있는 내용을 한 줄 변경한 뒤 변경된 레이어를 역상으로 표시하였습니다.

우리는 코드 한 줄을 수정하였지만, 실제 새롭게 변경된 이미지 레이어는 무려 568MB 이상입니다. 이런 형태로 개발을 하다 보면 다음과 같은 문제에 직면하게 됩니다.
이제 변경한 Dockerfile 의 내용을 확인해 보겠습니다.
FROM pytorch/pytorch:latest
ENV PYTHONUNBUFFERED 1
COPY source/requirements.txt /app/source/
RUN pip install –-upgrade pip
RUN pip install -r \
/app/source/requirements.txt
COPY source/ /app/source/
CMD python /app/app.py
크게 달라진 점이 없기 때문에 꼼꼼하게 확인을 해보겠습니다. 확인하면 다음과 같이 변경된 것을 확인 할 수 있습니다.

이렇게 순서만 조금 바꾸는 것이 얼마나 큰 차이를 가져올까? 라고 생각할 수 있습니다. 그렇다면 실질적으로 나타나는 차이에 대해서 이야기 해보겠습니다.
Dockerfile 실행 순서 변경으로 반복적 이미지 생성 시 변경 되는 영역을 살펴 보겠습니다.

변경이 되는 영역과 사이즈를 확인해보면 36.5KB 뿐으로 이전의 568MB와는 비교하여 엄청 큰 차이가 납니다.
직접 이 내용을 따라 해보면 알겠지만 이전 구조에서는 이미지 빌드에 8분이 소요되던 것이 이번에는 2초도 안 걸릴 정도로 이미지 생성이 매우 빠르게 완료가 됩니다.
이미지 사이즈가 변경되는 점은 체감하기 힘들다고 해도 빌드 시간이 달라지는 것은 바로 체감이 될 것입니다. 이런 큰 차이는 어떻게 발생하는 것일까요?
바로 우리가 수정하는 코드 자체는 매우 일부분이기 때문에 그 부분을 고려해야 한다는 것입니다. 앞서 컨테이너 이미지를 생성할 때 레이어링 과정을 통해 명령을 수행한 순서대로 결과를 저장한다고 했습니다.
우리가 변경하는 것은 최종 레이어가 만들어지기 직전에 수정을 해야 하는 것이지, 변화가 거의 없는 라이브러리 설치 과정 전에 작성한 코드를 복사하면 안되는 것입니다. 코드가 동작하기 위해서 필요한 환경부터 만들어 두고 작성한 코드를 복사하는 것이 효율적일 것입니다.
변경하는 코드는 전체 영역에서 매우 일부분이고 변경이 자주 일어나기 때문에 가장 최상위 레이어에서 변경하여 변경되지 않는 영역은 최대한 재활용 해야 합니다. 만약 이 과정을 고려하지 않는다면 일부 코드의 수정으로 인해서 매번 라이브러리를 새롭게 설치하고 그로 인해서 용량도 불필요하게 계속 사용하는 상황이 발생합니다.
이 팁을 통해 8분이 걸리던 컨테이너 이미지 빌드 시간을 2초로 줄였으며, 568MB 씩 생성하여 보관하던 이미지 파일도 1MB 도 안되는 사이즈만 증가하는 형태로 변경하였습니다.
Dockerfile을 개선하는 방법은 더 없는지 궁금할 것입니다. 다음으로 작성할 내용은 '빌드 과정에 필요한 라이브러리는 모두 설치를 해야하는지?' 의 기준으로 추가 내용을 작성하겠습니다.