[Docker] /var/lib/docker/overlay2/ 무거워질 때 디버깅 및 우회법

식빵·2024년 11월 27일
0

docker reference

목록 보기
12/12
post-thumbnail

overlay2 디렉토리의 용도

이 디렉토리는 docker 의 imagecontainer 에 의해 생성되는
Layer(= 사실상 OverlayFS 에서 사용되는 File System 조각) 들이 저장되는 위치입니다.
정말 그런지는 아래처럼 테스트할 수 있습니다.

[root@dailycode overlay2]# \
docker pull hello-world
# Using default tag: latest
# latest: Pulling from library/hello-world
# c1ec31eb5944: Pull complete
# Digest: # sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966
# Status: Downloaded newer image for hello-world:latest
# docker.io/library/hello-world:latest

[root@dailycode overlay2]# \
du -hsx /var/lib/docker/overlay2/* 2> /dev/null | sort -rh | head -n 20;
# 20K     ./d0f70ef9eacfc28dbf701d230e576ebc1567932045500ac52689e1edcd7b17c7
# 0       ./l
# 0       ./backingFsBlockDev

위처럼 docker 에 image 가 하나도 없는 상태에서 pull 을 하고,
/var/lib/docker/overlay2 에 있는 디렉토리별 용량을 체크해보면 20K 짜리
하나가 생깁니다. 이게 바로 앞서 pull 한 이미지가 사용하는 Layer 입니다.


[root@dailycode overlay2]# \
docker run --name hello-world hello-world

# Hello from Docker!
# This message shows that your installation appears to be working correctly.
# 
# To generate this message, Docker took the following steps:
#  1. The Docker client contacted the Docker daemon.
#  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
#     (amd64)
#  3. The Docker daemon created a new container from that image which runs the
#     executable that produces the output you are currently reading.
#  4. The Docker daemon streamed that output to the Docker client, which sent it
#     to your terminal.
# 
# To try something more ambitious, you can run an Ubuntu container with:
#  $ docker run -it ubuntu bash
# 
# Share images, automate workflows, and more with a free Docker ID:
#  https://hub.docker.com/
# 
# For more examples and ideas, visit:
# https://docs.docker.com/get-started/

[root@dailycode overlay2]# \
du -hsx /var/lib/docker/overlay2/* 2> /dev/null | sort -rh | head -n 20;
# 20K     ./d0f70ef9eacfc28dbf701d230e576ebc1567932045500ac52689e1edcd7b17c7
# 8.0K    ./d59c7cd6014137045786fafd09793cb46b63e2e9eb599f318ae97fd778864f9e-init
# 8.0K    ./d59c7cd6014137045786fafd09793cb46b63e2e9eb599f318ae97fd778864f9e
# 0       ./l
# 0       ./backingFsBlockDev

이번에는 container 를 실행해보고 다시보죠.
마찬가지로 container 를 실행하면서 생기는 Layer 에 의해서 디렉토리 개수가
늘어나는 것을 확인할 수 있습니다.




overlay2 의 무거워지는 이유

무거워지는 이유는 단순히 image 가 용량이 정말 커서 그런 걸 수도 있습니다.
아니면 알 수 없는 이유로 쓰레기 Layer 가 있을 수도 있죠.

하지만 제가 생각하는 주 이유는 실행된 container 내부에서 기존 이미지 레이어와
파일 시스템 상 달라지는 부분에 의해서 생기는 데이터들 때문입니다.

-v 옵션 또는 volume 을 생성해서 사용하지 않은 상태로,
container 내부에 변동 사항이 생기면 이러한 모든 변동 사항이
overlays 디렉토리 내에 있는 upperDir (= container Layer 의 저장 경로)
에 누적됩니다.

이러면서 점점 overlay2 디렉토리가 무거워지는 거죠.




overlay2 디버깅하기

# 1. 테스트를 위해서 ubuntu container 하나를 띄우겠습니다.
docker pull ubuntu:24.04
docker run --name ubuntu-2404 -itd ubuntu:24.04

# 2. inspect 를 통해서 container layer 의 저장 위치를 찾아냅니다.
docker container inspect ubuntu-2404 | grep -i UpperDir

# 출력결과: (너무 길어서 일부 생략했습니다)
# "UpperDir": "/var/lib/docker/overlay2/<생략>/diff",

# 출력결과에 나온 경로를 메모장이든 어디든 잠시 기록해둡니다.
# /var/lib/docker/overlay2/<생략>/diff <== 메모!

자, 이 상태에서 좀 더 쉬운 디버깅을 위해서 아래와 같이 화면을 두 개 띄우겠습니다.

왼쪽 화면은 실행 중인 container 내부로 들어가는 용도고,
오른쪽 화면은 du 명령어를 통한 지속적인 모니터링을 위한 것입니다.

왼쪽 화면은 아래와 같이 명령어를 입력합니다.

# 실행된 container 내부로 접속
docker exec -it ubuntu-2404 bash

오른쪽 화면은 아래와 같이 명령어를 입력합니다.

# 아까 알아낸 container Layer 저장경로(= upperDir) 로 이동
cd /var/lib/docker/overlay2/<생략>/diff

# 1초 마다 변동사항 확인
watch -n 1 'du -sh ./*'

이후에 아래처럼 좌측화면에서 something 이라는 디렉토리를 생성하고,
안에 계속해서 텍스트 파일을 생성하면 그에 따라서 좌측에서 계속 something 이라는
디렉토리의 용량이 늘어나는 것을 확인할 수 있습니다.

즉, 기존 이미지 레이어에는 없던 부분이 계속해서 생기면서
용량이 누적되는 것을 눈으로 확인할 수 있습니다.

이렇듯 계속해서 모니터링을 하면서 container 에 있는 애플리케이션의 기능들을
테스트하다가 비정상적으로 용량이 늘어나는 곳이 생기면? 그게 바로 문제가 되는 기능입니다.




overlay2 적재를 우회하는 방법

위의 디버깅 방식으로 뭔가를 찾아냈다고 칩시다.
만약에 컨테이너 내의 애플리케이션이 파일 시스템에 의도하지 않은 변화를 주면,
애플리케이션의 코드를 고치고 다시 container 로 띄우면 그만입니다.

하지만 만약에 애플리케이션이 파일 시스템에 변화를 주는 것이
애플리케이션의 의도된 동작이라면 조금 생각을 고쳐야 합니다.

이러한 의도된 동작이라 함은 다음과 같을 예시가 있습니다.

  • 애플리케이션 실행 로그
  • 비즈니스 로직에 의한 파일 저장/생성/삭제

보면 알겠지만, 이러한 의도된 동작들의 특징은 주로
컨테이너가 꺼져도 계속 유지되어야 하는 경우가 많습니다 ✔
그래서 자연스럽게 volume 이나 docker run -v 옵션을 사용하게 됩니다.


이럴 때는 overlay2 를 그대로 쓰지 말고,
docker run 을 할때 -v 옵션을 줘서 host pc 의 용량이 넉넉한
디렉토리와 바인딩해주는 게 좋습니다.

또는 volume 을 생성하고, mount 를 하는 방법도 있습니다!

이렇게 바인딩된 디렉토리는 overlay2 에 용량을
늘리거나/줄이는 현상을 일으키지 않습니다.

테스트해보죠.


좌측화면

# 기존에 돌던 container 삭제
docker rm -vf ubuntu-2204

# 다시 실행, 대신 -v 옵션 추가
docker run -v /something:/something --name ubuntu-2404 -itd ubuntu:24.04

# HOST 에 바인딩한 디렉토리로 이동
cd /something

우측화면

# docker run 이 완료된 후
# docker container inspect ubuntu-2404 | grep -i "UpperDir"
# ...를 입력해서 upperDir 경로 조회 및 이동 후에 아래 명령어 입력
watch -n 1 'du -sh ./*'

보시면 알겠지만 바인딩한 위치에 아무리 파일을 생성해도, 용량의 변화가 없습니다.
혹시 실제로 해당 디렉토리에 파일이 안 생긴 게 아닐까? 하고 의심되시면
아래처럼 명령어를 입력해봅시다.

docker exec ubuntu-2404 ls /something


이상으로 글을 마치겠습니다.



참고한 것들

profile
백엔드를 계속 배우고 있는 개발자입니다 😊

0개의 댓글