7일차_볼륨, 마운트

최지웅·2024년 11월 6일
0

인프라

목록 보기
10/19

6-1. 컨테이너 속 데이터가 사라지는 이유

  • 모든 컨테이너가 공유하는 이미지 레이어는 읽기 전용이고, 각 컨테이너가 따로 갖는 기록 가능한 레이어는 컨테이너와 같은 생애주기를 갖는다.
  • 도커 컨테이너에서 수정한 파일은 실제 파일을 수정한 것 처럼 사용되지만, 실제로는 원본을 냅두고 컨테이너 위에서 기록가능 레이어를 따로 만들어 수정중인 것으로 컨테이너 종료 시 수정한 내용은 사라진다.
  • 여기에서 중요한 것은, 컨테이너를 대체하여 업데이트 하는 경우에 해당 컨테이너의 데이터가 모두 손실된다는 것이다.
# 로컬에서 컨테이너로 파일 복사 후 출력
docker container run --name f1 diamol/ch06-file-display
echo "http://eltonstoneman.com" > url.txt
docker container cp url.txt f1:/input.txt
docker container start --attach f1

#새 컨테이너를 실행해 확인해보면 내용이 그대로이며, 삭제후엔 수정 데이터가 사라진다.
docker container run -name f2 diamol/ch06-file-display
docker container rm -f f1
docker container cp f1:/input.txt
  • 이를 해결하기 위해 컨테이너와 별개의 생애주기를 가지는 도커 볼륨과 마운트가 있다.

6-2. 도커 볼륨을 사용하는 컨테이너 실행하기

  • 볼륨을 생성해 사용하면 컨테이너 파일 시스템의 한 디렉터리가 되기에 새로운 컨테이너에 볼륨을 다시 연결하면 기존 데이터가 유지된다.
# 멀티 스테이지 빌드 Dockerfile 스크립트 일부
FROM diamol/dotnet-aspnet
WORKDIR /app
ENTRYPOINT ["dotnet", "ToDoList.dll"]

VOLUME /data # /data디렉터리는 볼륨에 영구 저장
COPY --from=builder /out/ .
  • 빌드 스크립트에 VOLUME으로 볼륨을 설정해두면, 아래와 같이 실행 시 자동으로 볼륨 생성해서 연결시킨다.
docker container run --name todo1 -d -p 8010:80 diamol/ch06-todo-list
docker container inspect --format '{{.Mounts}}' todo1 # mounts항목에서 볼륨 정보를 볼 수 있다(연결이 정상적으로 되었다)
docker volume ls # 볼륨 목록 확인
  • 아직까지는 위처럼 도커 이미지에서 볼륨을 정의하면 컨테이너 생성할 때 마다 새로운 볼륨을 만든다. 이때 volumes-form 플래그를 적용하면 다른 컨테이너의 볼륨을 연결할 수 있다.
docker container run --name todo2 -d diamol/ch06-todo-list # todo2 컨테이너 실행
docker container exec todo2 ls /data # (linux) todo2에서 /data(볼륨) 목록 출력
docker container run -d --name t3 --volumes-form todo1 diamol/ch06-todo-list # 새로운 t3 컨테이너 실행(with volums-form)
docker container exec t3 ls /data # (linux) todo3에서 /data(볼륨) 목록 출력. 같은 목록이 출력된다.
  • 하지만 동시성 문제 때문에, 볼륨은 컨테이너 간 파일 공유가 아닌 업데이트 시 기존의 상태를 보존하기 위한 용도로만 사용해야한다. 또, 볼륨에 이름을 붙여서 명시적으로 관리하는 것이 가독성에 좋은데, 아래가 예시이다.
target='/data' # 복사 대상 경로

docker volume create todo-list # 데이터 저장할 볼륨을 명시적으로 생성

docker container run -d -p 8011:80 -v todo-list:$target --name todo-v1 diamol/ch06-todo-list # -v태그로 todo-list볼륨의 복사 대상 경로를 연결

# http://localhost:8011에서 몇개 데이터 추가

docker container rm -f todo-v1 # 컨테이너 삭제

docker container run -d -p 8011:80 -v todo-list:$target --name todo-v2 diamol/ch06-todo-list:v2 # 데이터 보존
  • 주의할 점은 Dockerfile 스크립트의 VOLUME과 docker container의 --volume플래그는 별개이기에 docker container run 시 볼륨을 지정하지 않으면 항상 새로운 볼륨을 함께 생성한다. 즉, 볼륨을 사용할거면 Dockerfile과 컨테이너 run 시 --volume을 함께 기억하자.

6-3. 파일 시스템 마운트를 사용하는 컨테이너 실행하기

  • 볼륨은 컨테이너와 분리되어 있는 반면 직접적으로 연결시키는 수단으로 '바인드 마운트'가 존재한다. 이는 호스트 컴퓨터 파일 시스템의 디렉터리를 컨테이너 파일 시스템의 디렉터리로 만든다. 약간 pc 구글 드라이브 느낌인듯.
source="$(pwd)/databases" && target="/data" # (linux) source가 로컬 디렉터리, target이 컨테이너의 타켓 디렉터리

mkdir ./databases

docker container run --mount type=bind,source=$source,target=$target -d -p 8012:80 diamol/ch06-todo-list # 바인드 마운트

curl http://localhost:8012 # 8012포트에 run중인 컨테이너에 http요청을 보내 어플리케이션이 시작되며, DB파일이 생성된다.

ls ./databases # 컨테이너에 생성된 DB파일을 bind mount된 현재 dir에서 볼 수 있다.
  • 바인드 마운트는 양방향이기에 최소 권한을 가진 계정으로 실행된 컨테이너이기에, Dockerfile 스크립트에서 USER 인스트럭션을 사용해 컨테이너에 관리자 권한을 부여해야한다.
  • 중요한 것은, 바인드 마운트 방식으로 분산 스토리지들을 컨테이너에 연결해서 유상태 어플리케이션에 사용하여 신뢰성을 개선시킬 수 있지만, 몇가지 한계가 존재한다.

6-4. 파일 시스템 마운트의 한계점

    1. 마운트 대상 디렉터리가 이미 존재하며 이미지 레이어에서 이 디렉터리의 파일을 포함하고 있다면? 이미 존재하는 디렉터리에 마운트하면 원본 디렉터리가 기존 디렉터리를 완전히 대체하여 이미지에 포함되어 있던 파일을 사용할 수 없다. 결과적으로, 바인드 마운트를 하면 그 전에 이미지 자체에 있던 파일들을 사용할 수 없다.
    1. 호스트 컴퓨터의 파일 하나를 디렉터리로서 마운트하면? 파일과 기존의 마운트된 파일이 모두 나타난다. 이때 리눅스와 윈도우의 처리가 각각 다르다.
    1. 분산 파일 시스템을 컨테이너에 바인드 마운트하면 정상 동작할까? 이론상 모든 데이터에 접근가능하겠지만 그 안에 Azure, AWS S3 등을 사용하고 있다면 파일 시스템 차이로 지원되지 않는 동작이 있을 수 있다. 중요한 것은, 분산 스토리지 마운트는 성능저하외에도 많은 위험을 고려해야한다.

6-5. 컨테이너의 파일 시스템은 어떻게 만들어지는가?

  • 모든 컨테이너는 도커가 모아 만든 단일 가상 디스크로 구성된 '유니언 파일 시스템'을 따른다. 하지만 기록 가능한 레이어는 하나밖에 가질 수 없다.
  1. 기록가능레이어: 캐싱 등 단기 기억. 컨테이너 삭제시 유실
  2. 로컬 바인드 마운트: 호스트랑 컨테이너 간 소스코드 전달
  3. 분산 바인드 마운트: 가용성 높은 공유캐시, 성능차이 있음
  4. 볼륨 마운트: 어플리케이션 데이터 영구 저장, 이전 버전 컨테이너의 데이터 유지 가능
  5. 이미지 레이어: 컨테이너 초기 파일 시스템 구성, 읽기 전용으로 여러 컨테이너가 공유. 적층구조를 쌓음.
profile
이제 3학년..

0개의 댓글