Docker 의 기본 스토리지 드라이버 overlay2 는 리눅스 OverlayFS 로 이미지 레이어와 컨테이너의 쓰기 레이어를 겹쳐 하나의 파일 시스템처럼 보여 준다. 디스크가 차는 원인을 찾거나 컨테이너를 지웠을 때 무엇이 사라지는지 판단하려면 이 구조를 알아야 한다.
| 이름 | 역할 | 쓰기 |
|---|---|---|
| lowerdir | 이미지 레이어. 여러 개가 아래에서 위로 쌓인다 | 읽기 전용 |
| upperdir | 컨테이너가 만든 변경분. Docker 디렉터리에서는 diff/ |
읽기 · 쓰기 |
| workdir | OverlayFS 가 원자적 복사에 쓰는 내부 작업 공간 | 내부용 |
| merged | 위를 합쳐 컨테이너 안에서 / 로 보이는 뷰 |
마운트 지점 |
/var/lib/docker/overlay2/<id>/lower 파일에 아래 레이어들의 식별자가 : 로 이어져 적혀 있고, mount | grep overlay 로 실제 마운트 옵션(lowerdir=...,upperdir=...,workdir=...)을 볼 수 있다.
파일을 읽을 때는 upperdir 에 있으면 그것을 쓰고, 없으면 lowerdir 을 위에서부터 찾는다. lowerdir 의 파일을 고치면 먼저 upperdir 로 통째로 복사한 뒤(copy-up) 거기서 수정하므로 이미지 레이어는 바뀌지 않는다. 큰 파일을 한 바이트만 고쳐도 전체가 복사되는 것이 OverlayFS 의 비용이다.
삭제는 아래 파일을 실제로 지우는 것이 아니라 upperdir 에 whiteout 항목(주·부 번호가 0 인 문자 장치)을 만들어 가리는 방식이다. 그래서 Dockerfile 에서 RUN rm 으로 지워도 앞 레이어의 용량은 그대로 남는다. 이미지를 줄이려면 같은 RUN 안에서 받고 지우거나 멀티스테이지 빌드를 쓴다.
컨테이너가 만든 로그 · 임시 파일 · 추가 설치분은 전부 upperdir 에 쌓인다. /var/lib/docker 가 가득 찼다면 대개 여기가 원인이다.
docker system df -v
du -sh /var/lib/docker/overlay2/*/diff | sort -h | tail
컨테이너를 지우면 upperdir 도 함께 사라진다. 남겨야 하는 데이터는 볼륨이나 바인드 마운트에 둔다. 반대로 lowerdir 은 같은 이미지를 쓰는 모든 컨테이너가 공유하므로 베이스 이미지를 통일하면 디스크와 pull 시간이 함께 줄어든다.
Docker Engine 29 부터는 containerd 이미지 스토어가 기본이라 이미지 레이어는 containerd 스냅샷터 쪽에 놓이고 overlay2/ 에는 컨테이너 쓰기 레이어 위주로 남는다. 경로가 다를 뿐 lower 와 upper 의 관계는 같다.