Oh My Algorithm
Concept GuideUnion FS · 레이어 캐시 · 멀티스테이지

이미지 레이어와 용량 (Layers & Size)

Docker 이미지는 하나의 통짜 파일이 아니라 읽기 전용 레이어를 겹겹이 쌓은 구조입니다. Dockerfile의 명령 하나가 레이어 하나를 만들고, 실행 시 그 위에 쓰기 가능한 컨테이너 레이어가 얹혀 하나의 파일시스템처럼 보입니다. 레이어는 내용이 같으면 이미지끼리 공유되고 캐시되기 때문에 명령 순서가 곧 빌드 속도를 정하고, 최종 이미지에 어떤 레이어를 남기느냐가 용량을 정합니다 — 멀티스테이지 빌드는 빌드 전용 레이어를 통째로 버려 같은 앱을 1 GB대에서 100 MB대로 줄입니다.

01이미지 레이어와 용량 (Layers & Size)

Docker 이미지는 하나의 통짜 파일이 아닙니다. 읽기 전용 레이어를 겹겹이 쌓은 구조이고, Dockerfile의 명령 하나가 레이어 하나를 만듭니다.

FROM node:20-alpine · 베이스 이미지를 맨 아래에 깝니다. alpine 리눅스와 Node 런타임이 들어 있는 140 MB짜리 바닥입니다.

COPY package*.json · 의존성 '목록'만 먼저 복사합니다. 4 KB짜리 얇은 레이어지만, 앱 소스보다 훨씬 덜 바뀐다는 점이 중요합니다.

RUN npm ci · 의존성을 설치합니다. 180 MB짜리 node_modules가 통째로 한 레이어가 됩니다 — 가장 무겁고, 가장 다시 만들고 싶지 않은 레이어입니다.

COPY . . · 마지막에 앱 소스를 얹습니다. 가장 자주 바뀌는 것을 맨 위에 두는 것이 레이어 설계의 핵심입니다.

여기까지가 이미지입니다. 유니온 파일시스템이 네 레이어를 겹쳐 하나의 파일시스템처럼 보여줍니다 — 안쪽이 베이스, 바깥이 최신 레이어입니다.

컨테이너를 실행하면 이미지 위에 쓰기 가능한 레이어가 하나 더 얹힙니다. 실행 중의 모든 변경은 아래 레이어를 건드리지 않고 여기에만 기록됩니다(Copy-on-Write).

앱 소스만 고쳤다면? 바뀐 건 맨 위 레이어뿐입니다. 아래 세 레이어의 캐시가 그대로 재사용돼 재빌드가 몇 초에 끝납니다.

반대로 package.json을 건드리면 그 위 레이어의 캐시가 전부 무효화됩니다. npm ci부터 다시 돌아 빌드가 몇 분으로 늘어납니다 — 명령 순서가 곧 빌드 속도입니다.

그런데 이렇게 쌓아 만든 이미지가 1.1 GB 입니다. 단일 스테이지로 빌드하면 만드는 동안 생긴 것이 전부 최종 이미지에 그대로 남기 때문입니다. 높이가 곧 용량입니다.

가장 큰 덩어리는 devDependencies 420 MB 입니다. 타입스크립트 컴파일러·번들러·테스트 러너 — 빌드할 때만 쓰이고 실행할 때는 한 줄도 쓰이지 않습니다.

네이티브 모듈을 컴파일하려고 설치한 python·make·g++ 190 MB 도 남아 있습니다. 도구가 남아 있다는 건 공격 표면이 그만큼 넓다는 뜻이기도 합니다.

정작 실행에 필요한 건 파랗게 칠한 dist/ 12 MB 뿐입니다. 1.1 GB 중 1 % 가 조금 넘습니다 — 저 얇은 띠 하나 때문에 나머지를 전부 지고 다닌 셈입니다.

멀티스테이지는 빌드용 스테이지를 따로 두고, COPY --from=builder 로 산출물만 다음 스테이지로 옮깁니다. 앞 스테이지는 최종 이미지에 포함되지 않습니다.

그 결과 회색 덩어리가 통째로 사라집니다. 남는 것은 슬림 런타임 140 MB, 운영 의존성 3 MB, 그리고 아까 그 dist/ 12 MB 입니다.

node:20140 MB
1 / 15

정리

레이어는 내용이 같으면 이미지끼리 공유되고, 순서가 캐시를 정합니다. 그리고 최종 이미지에 무엇을 남기느냐가 용량을 정합니다 — 같은 앱이 1.1 GB 에서 155 MB 로 줄어든 이유입니다.

02 쉽게 이해하기

For Everyone
🔑핵심 동작

이미지는 읽기 전용 레이어를 쌓은 것이고 Dockerfile 명령 하나가 레이어 하나를 만듭니다. 유니온 파일시스템이 이들을 겹쳐 한 파일시스템으로 보여 주며, 중간 레이어가 바뀌면 그 위 레이어의 캐시가 전부 무효가 됩니다.

💡쉽게 말하면

Dockerfile의 FROM·COPY·RUN 같은 명령이 각각 읽기 전용 레이어를 만들고, 유니온 파일시스템이 이들을 겹쳐 하나로 보여줍니다.

컨테이너를 실행하면 맨 위에 쓰기 가능한 레이어가 추가되고, 변경은 전부 여기에만 기록됩니다(Copy-on-Write).

어떤 레이어가 바뀌면 그 위 레이어의 캐시는 모두 무효화되므로, 자주 안 바뀌는 것(의존성 설치)을 아래에, 자주 바뀌는 것(앱 소스)을 위에 두는 것이 핵심입니다.

📍어디에 쓰나
  • Dockerfile 명령 순서 최적화
  • 빌드 캐시 적중률 높이기
  • 멀티스테이지로 이미지 용량 줄이기
  • 여러 이미지가 베이스 레이어를 공유하는 원리 이해

03 자주 묻는 질문

FAQ
이미지 레이어와 용량 (Layers & Size)란 무엇인가요?+

Docker 이미지는 하나의 통짜 파일이 아니라 읽기 전용 레이어를 겹겹이 쌓은 구조입니다. Dockerfile의 명령 하나가 레이어 하나를 만들고, 실행 시 그 위에 쓰기 가능한 컨테이너 레이어가 얹혀 하나의 파일시스템처럼 보입니다. 레이어는 내용이 같으면 이미지끼리 공유되고 캐시되기 때문에 명령 순서가 곧 빌드 속도를 정하고, 최종 이미지에 어떤 레이어를 남기느냐가 용량을 정합니다 — 멀티스테이지 빌드는 빌드 전용 레이어를 통째로 버려 같은 앱을 1 GB대에서 100 MB대로 줄입니다.

이미지 레이어와 용량 (Layers & Size)은(는) 어디에 사용하나요?+

Dockerfile 명령 순서 최적화, 빌드 캐시 적중률 높이기, 멀티스테이지로 이미지 용량 줄이기, 여러 이미지가 베이스 레이어를 공유하는 원리 이해

이미지 레이어와 용량 (Layers & Size)를 쉽게 비유하면?+

이미지는 읽기 전용 레이어를 쌓은 것이고 Dockerfile 명령 하나가 레이어 하나를 만듭니다. 유니온 파일시스템이 이들을 겹쳐 한 파일시스템으로 보여 주며, 중간 레이어가 바뀌면 그 위 레이어의 캐시가 전부 무효가 됩니다.