Docker

[Docker] 5. Overlay FS & Storage

szoo_ 2024. 9. 14. 21:16

이번에 배울 것은 Union File System인 Overlay FS(file system)이다.

사실 대부분의 도커를 배우게 된다면 해당 그림을 제일 접할 것이다. 가장 중요하면서도 어려운 부분이라고 생각한다.

 

근데 나 같은 경우엔, 맨 처음 이것에 대해 배우고 실습을 했지만 도커를 잘 사용할 수 있었음에도

이것에 대한 개념을 제대로 파악하지 못했었다.

 

조금의 시간이 지나며 차차 도커의 이미지 레이어 개념을 파악하고, 떠올리며 차차 이해되기 시작했다.

그래서 도커 레이어에 대한 글을 쓴 이후에서야 글을 작성하게 되었다.


What is Overlay FS? 

리눅스 파일 시스템의 한 유형으로, 두개의 디렉토리를 하나의 디렉토리처럼 겹쳐서 표현 할 수 있게 해주는 "유니온 파일 시스템(Union File System)이다.

이러한 디렉토리를 레이어(Layer)라고 하고, 파일 시스템은 통합 프로세스를 "유니온 마운트(Union Mount)"라고 하며, 
두개의 디렉토리를 각각 하위 디렉토리(lowerdir)상위 디렉토리(upperdir)로 참조한다.

 

또한 사용자는 이 두 레이어가 합쳐진 형태로 볼 수 있게 제공되는 Merged로 볼 수 있다. 

 

Overlay2에서는 최대 128개의 레이어를 생성할 수 있다.

 

더 자세히 알아보자.

  • Lowerdir: 기본적으로 읽기 전용으로 설정되며, 기본 데이터가 저장되는 위치이다.
  • Upperdir: 변경사항을 저장하는 읽기/쓰기 가능한 디렉토리이다.
  • Merged: Upperdir과 Lowerdir의 결합된 결과를 보여주는 디렉토리로, 통합된 뷰를 제공한다. 

Lowerdir은 읽기 전용으로 바뀌지 않는다.

Upperdir은 만약 바뀐 사항이 있으면 기록한다.

Merged는 두개를 합쳐서 하나의 뷰로 보여지게 한다.

 

이것을 보며 두가지 생각이 들것이다.

 

첫째, "우리가 평소에 사용하던 리눅스도 이렇게 작동하는 거였나?"

 

그건 아니다. 

일반적인 리눅스 파일 시스템으로는 Ext4, XFS 등이 있는데 궁금하면 검색해서 찾아보자.

 

둘째, "Lowerdir은 읽기 전용이라는데 그럼 맨 처음 Lowerdir은 어떻게 기록된거야?"

 

이것에 대한 답은 아래에서 차차 설명하겠다.


한번 단순히 생각해보자(OverlayFS를 고려하지 않은 상태에서 말이다)

도커 컨테이너를 시작하면 아래와 같은 그림이 될 것이다.

그럼 지금 호스트에서는 Docker ImageApplication의 데이터 모두 들고 있어야 한다.

 

만약 컨테이너가 3개라면?

 

Docker Image Application 1,2,3의 데이터를 모두 들고 있어야 할 것 이다.

필요한 저장 용량이 크지 않겠는가? 가뜩이나 이미지의 크기도 큰데 비효율적이라는 생각이 든다.

그럼...어떻게 해야 할까?

 

우리는 이미 답을 알고 있다. 

Application 1,2,3은 모두 같은 이미지를 쓰고 있다.

그렇기 때문에 Docker Image는 기존 이미지를 그대로 사용하고 각 컨테이너마다 다른 정보만 저장하면 될 것이다.

그럼 새로운 컨테이너를 세팅할 때 이미 있는 이미지만 띄우고 만약 변경사항이 있다면 그것만 새로 기록하면 될 것이다.


자 이제 드디어 도커에서 OverlayFS 작동을 설명하겠다.

도커에서의 OverlayFS

맨 처음 보여줬던 사진이다.

사진을 자세히 보면 하나의 사실을 알 수 있다. 

  • Image Layer == Lowerdir
  • Container Layer  == Upperdir
  • Container mount  == Merged

알겠는가?

 

우리가 도커 파일로 도커 이미지를 만들면 생기는 것이  Image Layer. 즉, 가장 베이스가 되는 Lowerdir 이다.

그리고 컨테이너를 띄워 기존 이미지 외에 새로운 사항이나 변경사항이 생기면 기록되는 곳이 Container Layer = Upperdir 이다.

마지막으로 우리가 docker exec 로 접속해서 컨테이너의 데이터를 보는 것이 Container mount = merged 이다.

 

이렇게 도커 컨테이너는 OverlayFS를 통해 각 레이어로 나뉘어 자원을 효율적으로 관리 할 수 있는 것이다.


마지막으로 도커 컨테이너의 특징 하나를 설명하고 끝마치겠다. 이것도 중요하다.

 

도커 컨테이너는 기본적으로 무상태(stateless)이다.

이는 컨테이너의 상태에 대한 데이터(Container Layer)를 영구적으로 저장하지 않고,

컨테이너를 중지하거나 삭제 할 때 저장된 모든 데이터도 사라진 다는 것을 의미한다.

 

이러한 특성으로 인해, 도커 컨테이너의 관리가 용이해진다는 장점이 있다.

 

하지만 상태 유지가 필요한 경우가 있을 것이다.

왜냐하면 지속적으로 사용하고 싶은 입장에서는 데이터가 사라진다는 말처럼 들릴 것이다. 

그럼 도커의 볼륨(Volumes)이나 바운드 마운트(Bind Mounts)를 사용하여 데이터를 호스트 시스템이나 외부 스토리지에 저장 시킬 수 있다.

 

Docker Storage

이 둘의 차이점으로는 

  • 볼륨(Volumes): 호스트에 생성되는 파일이 도커에 의해 생성되고 관리 할 것인가
  • 바운드 마운트(Bind mount): 직접 호스트의 특정 파일에 연결하여 직접 관리 할 것인가

의 차이다.

둘 다 호스트에 생기는 것은 똑같기에 볼륨의 경우는  /var/lib/docker/volumes/  의 경로에 생성되는 것을 확인 할 수 있다.

 

도커(Volumes) 사용법

# 명시적 생성
docker volume create <name>

# 컨테이너에 볼륨 마운트 
docker run -v <볼륨이름>:<컨테이너 경로> <이미지>

만약 컨테이너를 실행시킬 때 특정 볼륨이 생성되어 있지 않아도 익명 볼륨 형태로 임의 생성되긴한다.

하지만 재사용은 불가능하다.

 

사용 사례로는

  • 여러 실행 중인 컨테이너 간의 데이터 공유
  • Docker 호스트에 특정 디렉토리나 파일 구조가 보장되지 않을 때
  • Docker 호스트에서 다른 호스트로 데이터 백업, 복원, 마이그레이션 할 때
  • 애플리케이션이 고성능 I/O를 요구할때
  • 아래 사진처럼 사용

도커 바운드 마운트(Bind mounts) 사용법

docker run -v <호스트 경로>:<컨테이너 경로> <이미지>

볼륨과의 차이점은 볼륨은 <볼륨이름>:<컨테이너 경로>이고  바운드 마운트는 <호스트 경로>:<컨테이너 경로>이다.

 

주의 할 점으로

호스트 경로는 실제로 있는 경로이어야만 한다.

만약 특정 폴더가 없는 폴더 또는 잘못된 경로라면 해당 컨테이너가 제대로 실행되지 않는 것을 목격 할 수 있다.

 

사용 사례로

  • 호스트 머신에서 컨테이너로 구성 파일을 공유 할 때
  • Docker 호스트의 개발환경과 컨테이너 간에 소스 코드나 빌드 산출물을 공유 할 때
  • Docker 호스트 파일이나 디렉토리 구조를 그대로 사용하여 컨테이너 안에서의 파일 구조를 일관적으로 들고 있게할 때

 

이상으로 도커의 설명을 마치도록 하겠다.