Linux Kernal - OverlayFS
------------------------
- 커널에 내장된 파일시스템 드라이버.
- "mount -t overlay" 시스템 콜로 lowerdir, uppderdir, merged를 마운트하는 "실제 엔진"
Docker - overlay2 스토리지 드라이버
----------------------------------
- 커널 OverlayFS를 "호출해서 쓰는 Go 코드"
- 레이어 디렉토리 관리, 캐시 판단 등의 관리 로직
- 별도 파일시스템이 아님
=> Docker를 설치해도 overlay2가 2개가 되는 게 아니라, 커널의 OverlayFS 위에 "관리 계층"이
얹어지는 것
/var/lib/docker/overlay2/<해시>/
├── diff/ ← 이 레이어의 파일 내용 (변경분)
├── link ← 짧은 심볼릭 링크 ID
├── lower ← 하위 레이어 참조
├── work/ ← OverlayFS 내부 작업용
└── merged/ ← 컨테이너 실행 시에만 생김
- "diff/"가 핵심
- 이미지 레이어의 "diff/"는 "lowerdir(읽기 전용)"으로 쓰이고,
컨테이너 레이어의 "diff/"는 "upperdir(쓰기 가능)"으로 마운트 됨.
1. 이전 레이어들을 "lowerdir"로 깔고, 빈 upperdir(diff/)로 임시 컨테이너 생성
2. merged/ 안에서 명령어 실행 -> 변경사항이 "upperdir"에 기록
3. 실행 완료 -> upperdir 내용을 "새 디렉토리에 읽기 전용 레이어로 커밋"
4. 임시 컨테이너 삭제(upperdir, merged 마운트 해제)
5. 다음 명령어는 이 새 레이어를 lowerdir에 추가하고 1번부터 반복
핵심
----
upperdir은 임시로만 존재. 커밋 순간 새로운 독립 디렉토리가 변환되고 원래 upperdir은 사라짐.
upperdir에 계속 쌓이는 게 아니라 "매번 새 디렉토리가 생기는 것"
COPY build.gradle ./ <- 캐시 히트
RUN gradle dependencies <- 캐시 히트
COPY src/ ./src/ <- 캐시 미스
RUN gradle build <- 자동으로 캐시 미스(부모가 바뀌어서)
변화
/var/lib/overlay2/
|- a1.../diff/ <- build.gradle (기존 것 재사용)
|- f3.../diff/ <- gradle deps (기존 것 재사용)
|- d7.../diff/ <- 이전 src/ <- dangling(댕글링, 어떤 이미지도 참조 안된 레이어)
|- b1.../diff/ <- 이전 app.jar <- dangling
|- x8.../diff/ <- 새 src/ <- new
|- y2.../diff/ <- 새 app.jar <- new
아래 레이어도 변경되는 이유
"레이어 해시 = 부모 해시 + 명령어 + 입력"
그래서 체인처럼 엮여 있음
------------------------
FROM openjdk:17 → 해시: a1 = hash(없음 + "FROM openjdk:17")
COPY build.gradle → 해시: f3 = hash(a1 + "COPY build.gradle" + 파일내용)
RUN gradle deps → 해시: c9 = hash(f3 + "RUN gradle deps" + 없음)
COPY src/ → 해시: d7 = hash(c9 + "COPY src/" + 소스내용v1)
RUN gradle build → 해시: b1 = hash(d7 + "RUN gradle build" + 없음)
캐시 히트
---------
동일한 부모 레이어 + 동일한 명령어 + 동일한 입력 -> 기존 레이어 재사용
캐시 미스
---------
하나라도 바뀌면 그 시점부터 "이후 모든 레이어가 새로 생성."