인프라

도커에서 데이터를 관리하는 방법

teo_99 2023. 11. 18. 18:22

도커를 활용한 서비스 마이그레이션을 진행하고 있습니다. 이번 아티클에서는 도커에서 데이터를 관리하는 방법에 대해 알아봅니다.

 

Writable Layer의 휘발성 & 성능 이슈

도커 컨테이너는 실행 중 저장되는 정보를 Writable Layer (혹은 Container Layer라고도 불립니다)에 저장합니다. 그런데 이런 Writable Layer는 컨테이너가 삭제되면 같이 삭제된다는 특징을 갖고 있습니다. 따라서 어떤 데이터가 영구 저장되어야 한다면 컨테이너 내부에 저장하는 것은 좋지 못한 선택입니다.

 

또한 데이터가 영구적으로 저장될 필요가 없다고 하더라도 컨테이너 내부의 파일 시스템에 데이터를 저장하는 것은 지양되는 경우가 많습니다. 컨테이너 내부의 파일 시스템은 UFS(Union File System)을 사용하는데, 이는 실제 파일 시스템을 추상화해서 다루기 때문에 성능 측면에서 다소 떨어지는 부분이 있습니다.

 

이러한 문제들을 해결하기 위해 도커 컨테이너에 데이터를 저장하는게 아니라 호스트 머신에 저장하는 방법을 주로 사용합니다. 그리고 호스트 머신의 어느 부분에 데이터를 저장하느냐에 따라 크게 세 가지 방법이 존재하는데, 바로 volume, bind mounts, tmpfs mount 입니다.

https://docs.docker.com/storage/

참고로 세 가지 방법 모두 '컨테이너에 외부 저장소를 연결한다' 는 개념은 같습니다. 다만 차이점을 가지는 부분은 앞서 설명드렸듯이 '어디에 저장할지' 입니다. volume은 호스트 머신의 docker area에, bind mount는 file system에, tmpfs는 메모리에 연결하는 방식을 의미합니다. 이제 각각의 방식에 대해 조금 더 구체적으로 살펴보겠습니다.

 

docker volume 방식

처음으로 소개할 방식은 docker volume입니다. docker volume의 경우 호스트 파일 시스템의 특정 부분에 데이터를 저장하는 방식을 의미합니다. 구체적으로는 /var/lib/docker/volumes/ 디렉토리에 저장됩니다(리눅스의 경우). '이 영역은 도커 영역이야!' 라고 확실히 명시하는 방법이고, 가장 best practice에 가깝습니다. 

 

docker volume을 생성하고 컨테이너를 기동시켜 보겠습니다. 다음의 명령을 통해 도커 볼륨을 생성합니다. 그리고 'docker volume ls' 명령어를 통해 생성된 볼륨을 확인합니다.

 

 

이제 다음의 명령어를 통해 실제 컨테이너에 볼륨을 마운트합니다. 베이스 이미지로는 ubuntu를 선택하겠습니다. -v 옵션 혹은 --volume 옵션을 통해 볼륨을 컨테이너에 연결해줍니다. 아래 예시에서는 testvolume을 컨테이너의 /test 디렉토리에 연결하겠다는 의미입니다.

그리고 docke volume inspect 명령어를 통해 도커 볼륨의 정보를 확인해봅시다. MountPoint를 보시면 앞서 설명드렸다시피 지정된 경로에 생성되는 것을 확인할 수 있습니다. 참고로 볼륨명을 지정하지 않는 경우 도커에서 고유한 이름으로 디렉토리를 생성해주는데, 이를 익명 볼륨이라고 합니다.

실습이 끝났으므로 docker volume rm 명령어를 사용해 도커 볼륨을 삭제합니다. 이렇듯 도커 볼륨은 도커 명령어로 생성 / 삭제 / 마운트가 이루어지기 때문에 캡슐화된 방식이라고 볼 수 있겠습니다.

bind mount

두번째 방식은 bind mount 방식인데, 이는 도커 초기부터 사용할 수 있었던 방식이며 docker volume에 비해 기능이 제한적입니다. 도커 볼륨과 개념 자체는 상당히 유사하나, 호스트 머신의 실제 디렉토리를 임의로 참조할 수 있다는 점이 다릅니다. 앞서 도커 볼륨의 방식은 볼륨이 저장되는 디렉토리가 지정되었으나, bind mount 방식은 아무 경로나 지정해도 상관이 없습니다. 그렇기 때문에 호스트 머신의 디렉토리 구조에 의존적인 방법입니다.

 

도커 공식 문서에서는 bind mount보다는 도커 볼륨 방식을 권장합니다. 가장 큰 이유 중 하나는 도커 컨테이너가 호스트 머신의 디렉토리에 마음대로 접근할 수 있다는 것인데, 이는 도커 프로세스가 도커가 아닌 프로세스에게 영향을 미칠 수도 있기 때문입니다.

 

마찬가지로 간단히 실습을 해보겠습니다. 

 

앞선 도커 볼륨 생성 방식과 유사하지만 --mount 옵션 부분이 다릅니다. bind 타입으로 설정하고 src 디렉토리와 target 디렉토리를 설정합니다. 위 예시에서는 현재 작업 경로(pwd)를 컨테이너의 /test 디렉토리에 마운트하겠다는 의미입니다.

 

이후 컨테이너에 접속해 /test 디렉토리를 확인해보면 실제 호스트 머신의 디렉토리에 존재하는 파일들이 같이 드러나는 것을 확인할 수 있습니다. 참고로 docker-compose.yml, grafana-data, prometheus.yml 등은 제가 연습용으로 미리 만들어두었던 파일입니다.

 

tmpfs mount

tmpfs mount 방식은 데이터를 호스트 머신의 메모리에 데이터를 저장하는 방식입니다. 성능 상의 이유로 tmpfs 마운트 방식을 사용할 수도 있고, 혹은 호스트 머신이나 컨테이너에 저장되어서는 안되는 보안에 민감한 정보들을 다룰 때 사용할 수도 있습니다.

 

마찬가지로 실습을 통해 이해해봅시다. bind mount 방식과 유사하게 컨테이너를 기동합니다. 다만 type=tmfps로 설정하고 destination이라는 필드를 설정한다는 점에서 다릅니다.

 

desintation, 필드는 컨테이너 내부에서 어느 디렉토리에 마운트 시킬지를 결정하는 필드입니다. 위처럼 구성하는 경우 컨테이너 내부의 /test 디렉토리에 마운트됩니다.

 

마치며

도커에서 어떻게 저장소를 관리하는지를 알아보았습니다. 일반적인 상황에서는 docker volume을 사용하고, 성능이나 보안 이슈가 있는 상황이라면 tmpfs mount 방식을 사용하는게 좋아보입니다.

 

감사합니다.

 

참고 자료

https://docs.docker.com/storage/volumes/

https://docs.docker.com/storage/

https://medium.com/dtevangelist/docker-%EA%B8%B0%EB%B3%B8-5-8-volume%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-data-%EA%B4%80%EB%A6%AC-9a9ac1db978c