Infra/Docker(도커)

[Docker] 컨테이너 내부 데이터 영속적으로 관리하기 (Docker volume, mount)

민돌v 2023. 12. 5. 18:02

Docker 에서 생성되는 데이터를 영속적으로 관리하기 위한 효과적인 방법으로 볼륨과 마운트가 있습니다.
도커에서 제공하는 이 2가지 기능을 이요하여 로컬(Host)의 폴더와 컨테이너의 내부 폴더를 동기화 시킬 수 있습니다.

  1. Docker Volume
  2. Docker Bind Mount

 

이번 포스팅에서는 이 2가지 기능에 대해 정리해보고자 합니다.

 

[목차]

  1. Docker Container 내부에서 Data 저장 과정
  2. Docker 의 영속적 데이터 저장 방법
    1. 1) Volumes
      1. (1) 익명 볼륨 - Anonymous Volumes
      2. (2) 이름이 있는 볼륨 (명명된 볼륨) - Named Volumes
      3. (3)❗️ Volume의 메모리 저장 위치 (Mount Point)
    2. 2) Docker Bind Mount - 바인드 마운트
    3. 3) Tmpfs Mount

 

레츠고!


1. Docker Container 내부에서 Data 저장 과정

도커의 이미지와 컨테이너는 "레이어"를 쌓아가면서 만들어지고 → 그렇기 때문에 도커 이미지는 "불변"을 유지할 수 있습니다.

 

이 말을 실행중인 현재 파일을 저장하고자 하는  "컨테이너 입장"에서 "정리"해보자면,

  1. Docker Image를 빌드할 때 생성되는 레이어"호스팅 파일 시스템"에서 분리된 "자체 내부 파일 시스템"이 존재하고
  2. 이 이미지를 기반으로 도커 컨테이너를 시작하면 이미지 위에 "read-write" 레이어(Writable Layer) 로 컨테이너가 추가됩니다.
  3. 따라서 기본적으로 "read-write" 레이어는 이미지 파일 시스템에 엑세스할 수 있지만!
  4. 이미지 자체는 "read-only" 레이어이기 때문에 컨테이너는 파일을 생성할 때 상단에 추가되는 자체 "read-write" 레이어에 저장합니다.

이전 게시글 복붙!

 

이전 게시글에서 Docker 의 이미지를 지우는 방법 중 하나인 "docker run --rm" 옵션에 대해 말한적이 있었습니다.

결국 우리가 사용하게되는 도커의 방식은 [코드 변경] → [이미지 빌드] → [컨테이너화 & 실행] 이기 때문에
Docker 컨테이너는 굉장히 자주 삭제되는 품목입니다.

  • (컨테이너를 삭제시키지 않고 Git 과 같은 VSC(Version Control System) 을 이용하여 계속 사용하는 방법도 있습니다.)

 

📌하지만 컨테이너를 제거한다면 컨테이너 레이어에 저장된 데이터가 같이 삭제되기 때문에 컨테이너가 삭제되어도 생존해야만하는 데이터를 처리하는 방법이 필요합니다.

  • 예를들어) 에러로그, 실행로그, 실행파일, 환경변수 세팅 파일, 덥프파일 등등.

 


2. Docker 의 영속적 데이터 저장 방법

💡 Docker 에서는 Container 에 쓰여진 데이터가 도커 생명주기와 관련없이 영속적으로 저장이 되게하거나, Data를 안전하고 성능이 좋게 관리하기 위해 아래 3가지 방법을 제공합니다.

  1. Volumes
    1. Anonymous Volumes
    2. Named Voumes
  2. bind mounts
  3. tmpfs mount (

 

3가지 방식 모두 Docker에서 Data 를 안전하게(영속적으로) 저장시킬 수 있는 방법이지만, 
도커에서는 volume 을 가장 안전한 방법이라고 이야기 하고있으니,, 뭘 사용해야할지 모를때는 volume을 사용하라고 합니다.

 


1) Volumes

도커 볼륨이란?

  • 볼륨은 Docker 컨테이너에서 생성하고 사용하는 테이터를 지속하기 위해 선호되는 도커에서 제공하는 메커니즘입니다.
  • Docker 볼륨은 Docker 에서 완전하게 관리하는 호스트 머신의 폴더입니다. 
  • 컨테이너나 이미지에 있는게 아닌 호스트 컴퓨터에 장착된 하드 드라이브에 존재하여 사용가능하거나, 컨테이너로 매핑되는 것을 의미합니다.
  • 그렇기때문에 볼륨을 사용하면 컨테이너 내부에서 외부 파일에 접근할 수 있고, 외부에서 내부파일에 접근할 수 있는 "링크"를 제공해줍니다.
  • → 이러한 매커니즘으로 보륨을 통해 데이터를 유지할 수 있고, 연결된 컨테이너가 종료되더라도 계속 존재합니다.
    (단, 익명 불륨은 제외)

 

이러한 도커 볼륨에는 "익명 볼륨(Anonymous Volumes)""명명 볼륨(Named Volumes)" 2가지가 존재하고, 명확한 차이점이 존재합니다.


(1) 익명 볼륨 - Anonymous Volumes

  • 컨테이너 내부와 볼륨을 연결할 때, 연결할 볼륨을 명시하지 않으면 Docker Host 내에서 임의의 고유한 이름의 볼륨을 부여하고, 이를 이름이 부여되지 않았다 하여 익명 볼륨이라 합니다.
  • 익명 볼륨은 컨테이너가 존재하는 동안에만 존재합니다. 즉, 컨테이너가 종료된다면 볼륨도 사라집니다.
  • 실질적으로 컨테이너가 제거될 때 자동으로 제거되는 것은 아니지만, 새로운 컨테이너가 실행되면 새로운 익명 볼륨이 매핑되므로 기존의 익명 볼륨이 사용되지 않고 무의미하게 쌓이게만 됩니다.
  • 👏🏻 만약 '--rm' 옵션으로 컨테이너를 실행한다면, 컨테이너가 종료될 때 자동으로 익명볼륨도 삭제 됩니다.

 

[익명 볼륨을 컨테이너에 추가하는 방법 2가지]

1. DockerFile 에 추가하기

  • 이미지를 만드는 Dockerfile 에 "VOLUME" 명령어 추가하기
  • VOLUME["컨테이너 내부 경로"]
  • 내부 경로만 존재하기 때문에 도커에서 관리하는 특정한 폴더에서 볼륨이 관리되어집니다.
  • 그렇기 호스트에서 해당 파일을 찾기 힘듭니다.
  • 편집이 필요없거나, 직접 볼 필요가 없는 중요한 데이터에 적합한 볼륨 방식 입니다.
  • 익명 볼륨은 외부 경로보다 컨테이너 내부 경로의 우선 순위를 높이는데 사용할 수 있습니다.
FROM node
WORKDIR /app
COPY package.json /app
RUN npm install
COPY . /app
EXPOSE 80

#docker 익명 볼륨
VOLUME ["app/feadback"]

CMD ["node", "server.js"]

 

이렇게 유니크한 이름이 도커 자체적으로 부여됨

 

2. "-v" 옵션 사용하기

  • docker run "-v" 옵션을 사용하여 실행하는 컨테이너에 볼륨을 매핑할 수 있습니다.
  • docker run -v ['컨테이너 내부경로'] ['이미지 이름'] 으로 실행하면, 마찬가지로 컨테이너 내부경로만 존재하기 때문에 익명 볼륨이 매핑됩니다.
  • ex) docker run -v app/feadback anonymous-test-volumes1:latest 

 

(2) 이름이 있는 볼륨 (명명된 볼륨) - Named Volumes

  • Named Volumes 은 DockerFile 내부에서 생성할 수는 없고 컨테이너를 실행할 때 볼륨명을 지정하여 해당 이름으로 Docker Host 내에 볼륨을 부여할 수 있습니다.
  • ex) docker run -d -p 3000:80 --rm --name "컨테이너 이름" -v ['볼륨 이름':'컨테이너 내부경로'] ['이미지 이름']
  • 👏🏻 이름이 부여된 볼륨은 컨테이너 종료 후에도 도커에 의해 삭제되지 않고 유지됩니다.
  • 또한 볼륨이 생성되면, 다른 컨테이너에서도 해당 볼륨에 연결하여 데이터 공유가 가능합니다.

→ 1년전에 만들었던 Named 볼륨입니다. 실행중인 컨테이너가 없지만 해당 볼륨이 살아있는걸 볼 수 있습니다.
→ 참고로 익명볼륨은 '--rm' 옵션으로 실행하면 사라지지만 명명된 볼륨은 해당옵션으로 실행해도 컨테이너를 종료할 때 사라지지 않습니다.


(3)❗️ Volume의 메모리 저장 위치 (Mount Point)

  • volume 은 Docker(Linux 에서는 /var/lib/docker/volume/) 가 관리하는 Host File System 의 일부에 Data가 저장됩니다.

 

👏🏻 단 OS 가 리눅스가 아닌, 윈도우 맥이라면, 저 경로로 찾을 수 없습니다

  1. Mac os, windows os 에서 volume 을 찾을 수 없는 이유는 직접 os를 점유하지 않고, 호스트 os 를 공유하는 도커의  특성입니다.
  2. 리눅스 os 가 아니라면, Docker 는 Host 의 Kernel Socket을 공유합니다.
  3. 즉, Host Linux kernel을 대신할 것이 필요하기 때문에, Host 가 리눅스라면 있는걸 그대로 사용하면 되지만다른 OS 라면 Linux Kernel이 아니기 때문에 OS 위에 VM 으로 Linux 를 게스트 os 로 구동하고, 그 위에 Docker Engine을 구동합니다.
  4. 즉, 위의 명령어를 치면 나오는 주소인 "MountPoint" 는 Vm의 "MountPoint" 임을 의미합니다.
  5. 다른 OS 에서 Docker Volume에 접근하기 위해서는 screen 명령어 같은걸로 vm에 접속후 접근할 수 있다고 합니다.

mac 환경에서 찾을 수 없는 경로

 


2) Docker Bind Mount - 바인드 마운트

바인드 마운트란

  • Host 파일을 로컬 폴더 원하는 곳에 저장시키는 방법입니다. (원하는 폴더 동기화)
  • volume은  고정된 위치에서 데이터를 관리하기 때문에 원하는 곳에 파일을 저장시킬 수 없습니다.
  • Bind Mount를 사용하여 저장되는 Data는 System File이거나 Directory일 수 있습니다.
  • Docker Host 또는 Docker Container의 Non-Docker 프로세서들이 언제든지 저장된 Data를 수정할 수 있습니다.
docker run -v '내가 지정할 로컬 경로':/app/dockerDir  --name nginx-conatiner2 -p 8082:80 -d nginx

💡 (:) 콜론 앞에 로컬 머신 경로가 붙으면 바인드 마운트가 되고, 경로가 아닌 것이 붙으면 볼륨 이름으로 취금되어 명명된 볼륨이 됩니다

💡 바인드 마운트가 될 때, 호스트 머신에 마운트된 파일이 → 도커 내부 파일을 덮어 쓰기 때문에, 만약 이미지가 빌드될 떄 생성되는 종속성 폴더 같이 컨테이너 내부에 생성되는 보호해야할 파일이 존재한다면, 익명 볼륨을 사용하여 우선순위를 높여 보호할 수 있습니다.

-v 옵션을 사용하는 3가지 방법

 


3) Tmpfs Mount

  • Tmpfs : Temp File System 
  • 메모리에만 Data를 저장하는 방법입니다.
  • 즉, 영구적인 기억 장치가 아닌 휘발성 메모리에 저장됩니다.
  • tmpfs mount는 Host System의 Memory에만 Data가 저장되며, 절대로 Host의 File System에는 저장되지 않는다고 합니다.

 

Tmpfs 방식의 Mount 는 이 글에서 자세한 사항을 다루진않고 공식문서로 대체하겠습니다!

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

 

tmpfs mounts

Using tmpfs mounts

docs.docker.com

 

 

 


이렇게 Docker 컨테이너의 내부 데이터를 영속적으로 관리하는 방법에대해 정리해보았습니다.

 

도커 공식문서에서는 Bind Mount 보다 Volume이 성능이 더 좋다고 하고 권장하는 방식이라고 하는데

리눅스가 환경이 아니라면 Host Os에서 Volume 디렉토리에 접근하기가 꽤 귀찮고 까다로워서..

저는 Bind Mount를 주로 사용하게 되는 경향이 있었습니다

 

하지만 도커에서는 엄연히 Volume을 선호하고 보통의 Cloud 환경또한 Linux 기반의 os 로 시작하는게 보편적이기 때문에

볼륨을 유연하게 사용하는 방법에대해 고민해 봐야겠습니다 :)

 


* 참고