이미지를 경량화 해야지 외부 저장소로 push할 때도 빠르게되고, pull해올 때도 빠르게 됩니다. 그리고 이미지로부터 컨테이너를 띄우는 작업도 빨라지게 되고, 그리고 HostOS에서 동일한 용량대비 가질 수 있는 컨테이너의 양도 늘어나게 됩니다.
크게 이미지 경량화 전략은 3개 ( 컨테이너 레이어 수 줄이기, 경량 베이스 이미지 선택, 멀티 스테이지 빌드 사용 )이 있습니다.
컨테이너 레이어 수 줄이기
우선 Dockerfile에서 RUN명령어가 많아지게 되면, 그만큼 이미지 레이어가 쌓이게 됩니다. 이미지 레이어를 줄이기 위해서 RUN명령어를 최소화 하는 전략입니다.
기존에 작성된 Dockerfile을 보겠습니다. 저기 RUN지시어가 여러줄로 되어 있는 것을 보실 수 있을겁니다. 만약 저 RUN명령어를 &&문법을 통해서 연결되지 않았다면 RUN지시어가 2개가 더 추가가 되었을 것입니다. 즉 3개의 레이어를 1개로 줄였다고 보시면 될 것 같습니다.
그리고 사실 도커 이미지 상에서는 패키지에 대한 캐시가 필요하지 않습니다. 캐시를 남겨두게 되면 이미지의 용량만 늘어나게 된다는 단점이 있습니다. 때문에 패키지를 설치할 때, -no-cache와 같은 옵션이 있는지 잘 살펴보아야 합
니다. 그리고 불필요한 패키지를 삭제하고 캐시를 남기지 않는 것이 매우 중요합니다.
경량 베이스 이미지 선택
가장 많이 사용하는 전략입니다. 경량 베이스를 선택하는 방법입니다. 대표적으로는 debian slim, alpine, stretch가 있습니다. stretch는 파일시스템만 있는 것이기 때문에 매우 용량이 작습니다. 보통 컴파일 언어에서 사용됩니다. 보통 golang같은데에서 binary를 컴파일하고 stretch이미지에 복사해서 사용하는 용도로 사용됩니다.
기존에 nodejs-server는 위 Dockerfile로 빌드해서 이미지를 만들었었습니다.
그리고 이미지 목록을 보면 맨 위에 917MB라고 되어 있는데, 베이스 이미지인 node 16버전이 무려 910MB이기 때문입니다. 따라서 우리는 경량 베이스 이미지를 선택할 필요성을 느끼게 됩니다.
바로 debian기반의 slim경량 이미지를 깔았습니다. 이를 보게되면 기존 910MB와는 매우 차이가 큰 179MB가 됩니다.
그리고 16-alpine을 기반으로 하는 이미지 입니다. alpine리눅스는 도커 컨테이너를 위해 만들어진 리눅스 배포판이다보니까 매우 경량화된 이미지를 자랑합니다. 무려 115MB밖에 안되는 것을 확인하실 수 있습니다.
이제 사전에 작성된 Dockerfile.slim을 보게되면 베이스 이미지가 node:16-slim으로 바뀌어 있는 것을 보실 수 있습니다.
진짜 917MB -> 185MB로 경량화가 획기적이게 이루어진 것을 보실수 있습니다.
다음으로는 slim과 동일하게 alpine리눅스 배포판을 이용해 보도록 하겠습니다.
917MB -> 121MB로 엄청난 경량화가 일어난 것을 확인할 수 있습니다.
멀티 스테이지 빌드 사용
마지막으로 Docker의 기능입니다. 멀티 스테이지 빌드 기능을 사용하게되면, 빌드 스테이지와 릴리즈 스테이지를 나눠서 빌드때 필요한 빌드 의존성은 빌드 스테이지에서 진행하고, 릴리즈 스테이지에서는 빌드 결과물만 재사용해서 용량을 경량화 할 수 있게 됩니다.
우선 바로 Dockerfile을 보겠습니다. 이는 크게 3개의 Block으로 이루어져 있는데, 맨 위 base블럭, 그 아래 build블럭, release블럭이 있는 것을 FROM지시어로 확인할 수 있습니다.
build, release블럭의 FROM base의 의미는 base블럭을 재사용하겠다는 의미입니다. 그래서 base가 변경되지 않는 한 build, release블럭은 변경되지 않는 다는 의미입니다.
build 블럭이서는 package*.json에 해당하는 패키지를 /app에다가 다 다운 받는 역할을 합니다. 그 다음 release는 빌드된 결과를 바탕으로 --from=build를 두어 HostOS상이 아닌 GuestOS상에서 특정 스테이지에서 파일을 복사해 올 수 있습니다. 즉 build스테이지의 /app/node_modules를 /app/./noode_modules로 복사하겠다는 의미이고, 나머지 소스코드를 COPY지시어를 통해 복사합니다.
여기서 node_modules의 node server에 필요한 의존성 파일의 용량이 작기 때문에, 획기적인 경량화는 힘들지만 나중에 의존성 파일이 커지게 되면 획기적으로 줄게 됩니다. 일단 위 Dockerfile을 빌드해보겠습니다.
초기 alpine 리눅스 배포판을 사용한 121MB보다 4MB가 준 117MB가 되었습니다.
'DevOps > AWS Architecture' 카테고리의 다른 글
[ Docker && Kubernetes ] - 도커 컨테이너 다루기:명시적으로 여러 컨테이너 관리하기 (0) | 2022.09.04 |
---|---|
[ Docker && Kubernetes ] - 도커 컨테이너 다루기:도커 데몬 디버깅 (0) | 2022.09.04 |
[ Docker && Kubernetes ] - 도커 컨테이너 다루기:AWS ECR 저장소 이용 (0) | 2022.09.04 |
[ Docker && Kubernetes ] - 도커 컨테이너 다루기:도커허브 저장소 이용 (0) | 2022.09.04 |
[ Docker && Kubernetes ] - 도커 컨테이너 다루기:이미지 압축파일로 저장 및 불러오기 (0) | 2022.09.03 |