Post

[Docker] 도커의 데이터 외부 저장 매커니즘 볼륨과 바인드 마운트

컨테이너 데이터 저장의 한계와 볼륨

🐀 이미지는 읽기 전용이다

이미지와 컨테이너에는 로컬 폴더를 기반으로하는 자체 파일 시스템이 존재한다.
빌드된 이후에는 로컬 폴더와 이미지/컨테이너 내부 파일 시스템 사이에 연결은 없다.
⚠️ 컨테이너는 격리되어야 하기 때문에
즉, 이미지/컨테이너 내부 파일 시스템은 로컬 폴더의 스냅샷과 같다.

이미지 기반으로 컨테이너를 실행하면 이미지 위에 컨테이너 레이어(read-write)가 추가된다.
이미지는 읽기전용이기 때문에 데이터를 저장할 수 없고, 임시 데이터는 컨테이너(read-write)의 내부 파일 시스템에 저장될 수 있다.
임시 데이터밖에 저장을 못하는 이유는, 컨테이너를 삭제하면 당연히 내부 파일 시스템이 삭제되고 모든 데이터가 지워지기 때문이다.
⚠️ 컨테이너를 중지한다고 해서 내부 파일 시스템이 삭제되는 것은 아니다.

즉, 컨테이너가 삭제되어도 유지되어야 하는 영구 데이터는 컨테이너에 저장하지만 볼륨에도 저장해야 한다.

볼륨은 도커의 내장 기능으로 컨테이너가 실행되는 호스트 머신의 폴더를 말하는데, 이는 컨테이너나 이미지에 있는 것이 아니다.
즉, 도커 컨테이너 내부의 폴더호스트 머신의 특정 폴더를 매핑하여, 연결시키면 컨테이너는 해당 폴더에 데이터를 읽고 쓸 수 있다.
이후, 컨테이너가 종료/삭제된 경우에도 호스트 머신의 매핑된 특정 폴더(볼륨)에 계속 존재한다.

도커의 데이터 외부 저장 매커니즘

🐁 볼륨과 바인드 마운트

볼륨바인드 마운트의 가장 큰 차이는
볼륨은 도커가 관리하는 볼륨의 위치를 알 수 없지만, 바인드 마운트는 볼륨의 위치를 알고 있다.
바인드 마운트는 호스트 머신 상에 매핑될 컨테이너의 경로를 설정하기 때문이다.

  • 볼륨
    특정 데이터를 호스트 머신 파일 시스템에 아웃소싱할 수 있다. ⚠️도커 컨테이너에 의해 관리되지 x
    • 익명볼륨 anonymous volume
      컨테이너가 존재하는 동안에만 존재하며, 호스트 머신 내의 도커가 관리하는 어딘가에 숨겨져 있다.
      🎯 컨테이너에 이미 존재하는 특정 데이터를 (다른 모듈에 의해 덮어쓰이지 않게) 잠그는데 유용하다.
      🎯 성능 향상을 위해 temp 폴더를 익명볼륨에 매핑하면 유용하다.
      방법1 : VOLUME ["/app/test"] in 🐋 Dockerfile
      방법2 : docker run -v /app/test
    • 명명된볼륨 named volume
      컨테이너가 종료/제거된 후에도 볼륨이 유지되고, 특정 컨테이너에 국한되지 않는다.
      docker run -v test:/app/test 컨테이너를 실행할 때 명명된 볼륨을 만들 수 있다.
      영구적인 데이터 유지에 도움은 되지만, 편집은 불가능하다. 어디에 저장되있는지 모르니까
  • 바인드 마운트 bind mount
    컨테이너가 종료/제거된 후에도 볼륨이 유지되고, 특정 컨테이너에 국한되지 않는다.
    매핑된 호스트 머신 상 특정 폴더의 절대 경로를 알고 있기 때문에 영구적이고 편집가능한 데이터를 저장하는데 적합하다.
    🎯 소스코드를 바인드 마운트에 넣고, 컨테이너가 소스코드를 바인드 마운트에서 복사하면 실행 중인 컨테이너에서 변경된 코드를 적용시킬 수 있다.
    단, 바인드 마운트의 데이터를 지우려면 호스트 머신에서 삭제해야 한다. ⚠️ 도커 명령어로 지울 수 없다.
    docker run -v "HOST_MACHINE_ABSOLUTE_PATH:/app"
    바인드 마운트에 저장된 데이터(소스코드)를 덮어쓰는 것이다.

바인드 마운트의 소스코드를 덮어쓸 시 유의점

🪐 바인드 마운트의 소스코드에는 종속성 설치 결과가 존재하지 않는다

🐋 Dockerfile

1
2
3
4
5
# ... (생략)
COPY package.json .
RUN npm install
COPY . .
# ... (생략)

종속성 설치 후 그 결과인 node_modules 폴더는 🐋 docker build 시 생성되고,
생성된 node_modules 폴더까지 이미지에 복사한다.
즉, 로컬 머신의 매핑될 폴더(소스코드가 있는)에는 아직 node_modules가 존재하지 않는다.

하지만 이것을 docker run -v "HOST_MACHINE_ABSOLUTE_PATH:/app" 해당 명령을 통해 로컬 머신에 있던 소스코드로 덮어써 버리면
node_modules 폴더가 사라지기 때문에 실행에 오류가 생긴다.

때문에, 도커에게 외부에서 덮어쓰지 말하야할 폴더가 있음을 알려줘야 한다. 이는 익명볼륨을 추가해 해결할 수 있다.

도커는 항상 컨테이너에 설정하는 모든 볼륨을 평가하며
충돌이 있는 경우에는 더 구체적인 내부 경로를 우선한다.

즉, docker run -v "HOST_MACHINE_ABSOLUTE_PATH:/app" -v /app/node_modules 이런 식으로 명령을 작성하면
/app/node_modules/app 보다 더 구체적인 경로이기 때문에 (충돌이 생겼을 때) 해당 익명볼륨을 우선하게 된다.
때문에, 바인드 마운트의 데이터(소스코드)로 덮어쓰여지더라도 node_modules 폴더는 살아남을 수 있다.

📘 바인드 마운트를 읽기 전용 볼륨으로 전환
소스코드와 같이 실행 중에 변경해서는 안되는 컨테이너 내부 파일을 읽기 전용으로 국한하는 것이 좋다.
볼륨은 기본적으로 read-write 권한을 가지고 있는데, 이는 컨테이너가 볼륨에서 데이터를 읽고 쓸 수 있음을 의미한다.

docker run -v "HOST_MACHINE_ABSOLUTE_PATH:/app:ro"
🪶 Dockerfile의 COPY
로컬 호스트 머신의 소스코드 전체 폴더를 바인드 마운트로 바인딩하여
코드 변경사항이 실행중인 컨테이너에 자동으로 반영되게 하는데 여전히 Dockerfile에서 모든 항목을 COPY하는 이유

바인드 마운트로 바인딩은 docker run 명령시에 옵션으로 설정한다.
그리고 docker run 명령은 개발 중에 사용하는 명령이다.

즉, 바인드 마운트는 개발의 편리성을 위해 사용하는 것이지, 배포 환경에서 바인드 마운트를 사용하지 않는다.
때문에 production 환경에서는 항상 소스코드의 (변경되지않는, 일종의)스냅샷을 써야한다.
그래서 🐋 Dockerfile의 COPY 명령을 유지해 놓아야 한다.

도커 볼륨 관리

🐙 도커 볼륨 관리

볼륨은 도커에 의해 관리되고, 도커 컨테이너에 마운트된다.
도커에 의해 관리된다는 것은 컨테이너를 실행 할 때 볼륨이 존재하지 않으면 (자동)생성한다는 의미이다.

  • 🐋 docker volume ls
    현재 활성화된 볼륨을 모두 리스팅
    ⚠️ 바인드 마운트는 도커에 의해 관리되는 볼륨이 아니기 때문에 리스팅 되지 않는다.
  • 🐋 docker volume create VOLUME_NAME
    수동으로 볼륨을 생성
  • 🐋 docker volume inspect VOLUME_NAME
    볼륨 상세 정보 조회
    “Mountpoint”: “/var/lib/docker/volumes/VOLUME_NAME/data” ⚠️ 도커가 실행되는 가상 머신 내의 경로
    호스트 머신 파일 시스템에 있는 실제 경로가 아니다.
  • 🐋 docker volume rm VOLUME_NAME
    볼륨 제거
This post is licensed under CC BY 4.0 by the author.