BACKEND/Docker & Kubernetes

Docker Volume, 제대로 이해하기

gngsn 2024. 6. 3. 23:59

 

Storage in Docker

Docker가 로컬 파일 시스템에 데이터를 저장하는 방식에 대해 알아보겠습니다.

 

 

Docker의 파일 시스템 구조

도커를 처음 설치하면 /var/lib/docker 폴더가 생성되며, 다양한 하위 폴더들이 포함됩니다.

 

/var/lib/docker
├─ aufs
├─ containers
├─ image
└─ volumes

 

이 폴더들 하위에는 Docker 호스트에서 실행되는 이미지나 컨테이너와 관련된 데이터들이 저장됩니다.

 

 

 

 

 

Docker Layered architecture

Docker는 이미지를 구축할 때 레이어드 아키텍처를 사용합니다. 

Dockerfile를 빌드할 때 각 지시문마다의 레이어를 생성합니다.

 

 

각 지시어마다 레이어가 생성되고 사이즈가 측정됨

 

 

 

한 번 빌드된 레이어는 수정할 수 없으며, 새로운 빌드를 통해 재정의해야 합니다.

 

각 이전 레이어에서 변경된 부분에 한해 새로운 레이어를 생성하는데,

레이어들은 각 명령어의 변화크기를 반영하게 됩니다.

 

가령, 4번 째 줄부터 변경사항이 있는 아래 파일을 빌드하면,

 

동일한 지시어는 Cache 된 레이어 사용

 

 

변하지 않은 첫 3줄에 대해서는 캐시된 레이어를 재사용하여 빌드 속도와 이미지 사이즈 면에서 큰 효율을 가져옵니다.

 

이렇게 빌드된 이미지를 실행하면,

새로운 컨테이너 레이어이미지 레이어 위에 생성됩니다.

 

컨테이너 레이어는 쓰기 가능 (R/W) 하며, 컨테이너에 의해 생성된 데이터(로그 파일, 임시 파일 등)를 저장할 수 있습니다.

하지만 이런 파일들은 도커의 Copy-On-Write 전략으로 컨테이너가 살아있는 동안에만 유지됩니다.

 

 

Copy-On-Write Strategy

Copy-On-Write (aka. CoW) 는 쓰기 권한이 필요하면 복사본을 제공하는 전략입니다.

파일 혹은 디렉터리가 특정 레이어에 존재하고,

다음 계층에서 해당 파일의 편집 권한이 필요하다면 기존 파일을 복사해 편집할 수 있도록합니다.

이미지를 구축하거나 컨테이너를 실행할 때 파일은 해당 계층으로 복사됩니다.

 

이를 통해 I/O와 하위 계층 각각의 크기를 최소화할 수 있죠.

 

 

이미지 레이어의 복사 파일로 컨테이너 데이터 초기화

 

 

 

즉, 컨테이너는 이미지 레이어에서 복사해온 파일들로 초기화됩니다.

이후 복사본들에 접근하여 수정 하는 구조입니다.

컨테이너에서 수정해도 원본인 이미지 레이어의 읽기 전용 파일은 절대 수정할 수 없죠.

 

컨테이너 제거 시, 컨테이너 레이어의 모든 데이터가 삭제

 

 

 

컨테이너를 제거하면 컨테이너 레이어의 모든 데이터가 삭제됩니다.

그런데, 만약 데이터를 영구적으로 유지하고 싶다면 어떻게 해야 할까요?

 

 

 

Volumes

컨테이너 데이터를 영구적으로 저장하려면 Volume(이하 볼륨)을 사용해야 합니다.

먼저 볼륨을 생성합니다.

 

$ docker volume create data_volume

 

 

docker volume을 실행하면 /var/lib/docker/volumes 하위에 디렉터리가 생성됩니다.

 

/var/lib/docker
├─ aufs
├─ containers
├─ image
└─ volumes
   └─ data_volume

 

 

이후, 컨테이너 실행 시 docker run -v 명령어로 볼륨을 마운트합니다.

마운트를 하는 방법은 Volume Mounting 과 Bind Mounting 두 가지로 구분할 수 있습니다.

 

 

 

✔️ Volume Mounting

 

-v 옵션을 사용하여 볼륨을 마운트합니다.

 

$ docker run -v data_volume:/var/lib/mysql mysql

 

 

생성한 호스트 내의 data_volume 볼륨에 지정된 위치와 컨테이너 내의 /var/lib/mysql 이 마운트됩니다.

 

 

Volume Mounting

 


위 명령어를 실행하면, MySQL 데이터베이스의 모든 데이터는 Docker 호스트에 생성된 볼륨에 저장됩니다.
더 이상 컨테이너 레이어의 복사본을 사용하지 않아, 컨테이너가 파괴되어도 데이터는 유지됩니다.

 

볼륨 마운팅이라고 말해서 어려워 보일 수 있지만 사실상 두 디렉터리를 연결한 것이죠.

컨테이너 내에 저장하는 대신 호스트 디렉터리에 바로 저장해 컨테이너 생명 주기에 영향을 받지 않게 합니다.

이후 생성되는 컨테이너도 /var/lib/docker/volumes/data_volume 에 접근하면 이전 컨테이너와 동일한 파일을 참조하겠죠.

 

 

 

✔️ Bind Mounting

원하는 호스트 파일의 절대 경로를 사용해서 기존의 저장소 폴더를 마운트합니다.

 

$ docker run --mount type=bind,source=/data/mysql,target=/var/lib/mysql mysql

 

 

마찬 가지로 MySQL 데이터베이스의 모든 데이터가 Docker 호스트에 사용자가 지정한 특정 디렉토리에 저장됩니다.

 

 

 

 

Storage Drivers

🔗 Docker Storage Drivers

 

이상적으로는 컨테이너의 컨테이너 레이어에 데이터를 기록하지 않고,

도커 볼륨을 사용하여 데이터를 작성하는 것이 이상적입니다.

 

하지만, 일부 워크로드에서는 컨테이너 레이어에 데이터를 작성해야 합니다.

이 때 스토리지 드라이버가 사용합니다.

 

도커는 여러 개의 Storage Driver를 플러그인 형식으로 지원합니다.

Storage Driver는 이미지와 컨테이너가 도커 호스트에서 저장되고 관리되는 방식을 제어합니다.

스토리지 드라이버 개요를 읽은 후 다음 단계는 워크로드에 가장 적합한 스토리지 드라이버를 선택하는 것이다.

가장 일반적인 시나리오에서 전체 성능과 안정성이 가장 우수한 스토리지 드라이버를 사용한다.
도커 엔진은 리눅스에서 다음과 같은 스토리지 드라이버를 제공합니다:

 

Docker는 여러 종류의 스토리지 드라이버를 지원합니다.

 

Overlay2 - 현재 지원되는 리눅스 배포판에서 지원하는 가장 선호되는 스토리지 드라이버
- 추가 구성 필요 없음
fuse-overlays - Rootless overlay를 지원하지 않는 호스트 상의 Rootless Docker 를 실행하기 위해서만 선호됨
- Ubuntu 및 Debian 10 에서 사용될 필요가 없음
- overlay2는 Rootless 모드에서도 동작
- Rootless Mode Documentation 참조
BTRFS / ZFS - "스냅샷"을 만드는 것과 같은 고급 옵션을 허용하지만 더 많은 유지보수와 설정이 필요
- 각각 올바르게 구성하기 위한 backing filesystem에 의존함
VFS - vfs 스토리지 드라이버는 테스트나 Copy-On-Write 시스템에 적합하지 않는 상황을 위해서만 사용
- 성능이 좋지 않고 일반적으로 프로덕션 용으로 권장되지 않음

 

 

이 외에도 AUFS, BTRFS, Device Mapper 가 있습니다.

참고로, Ubuntu의 기본 스토리지 드라이버는 AUFS입니다.

Fedora나 CentOS는 AUFS를 지원하지 않으므로, 호환 문제가 생길 경우 Device Mapper를 사용하는 것이 좋습니다.