본문 바로가기
Docker

[Docker] 컨테이너에 저장된 데이터 유지(Volume Mount) | LIM

by forestlim 2023. 5. 10.
728x90
반응형

Docker 컨테이너 내부에 쓰인 데이터는 기본적으로 컨테이너가 삭제될 때 함께 사라진다. 따라서 Docker에서 수집한 데이터를 영속적으로 저장하기 위해서는 다른 방법이 필요하다. Docker 컨테이너의 생명 주기와 상관없이 데이터를 저장할 수 있도록 Docker는 두 가지 옵션을 제공한다. 첫 번째는 bind mount, 두 번째는 volume이다.

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

1. bind mount(바인드 마운트)

바인드 마운트는 호스트 시스템의 경로(파일 또는 폴더)가 컨테이너에 마운트 되는 형태이다. 경로가 존재하지 않으면 생성하여 마운트하고 호스트 시스템의 경로에 모두 접근할 수 있다. 사실 처음에 이 말만 들었을 때는 잘 이해가 안 됐는데 로컬에서 테스트해보니 이해가 되었다.

 

간단하게 코드를 통해 살펴보도록 하자.

 

data 폴더 내부 test.txt 텍스트 파일에 0부터 9까지 적는 코드이다. (main.py)

with open('./data/test.txt', 'a') as f:
    for i in range(10):
        f.write(str(i)+'\n')

 

이 코드를 Dockerfile을 정의해서 돌려보자.

FROM python:3.9

WORKDIR /app
COPY . /app

CMD ["python", "main.py"]

 

다음 명령어를 통해 docker 파일을 빌드하고 run 시킬 수 있다.

$ docker build . -t volume:test; docker run -d --name vol -p 8000:8080 volume:test

 

참고로 folder structure는 다음과 같다. 

그냥 돌리면 아무 일도 일어나지 않는다. docker 내부에서는 data폴더 내부에 test.txt 파일이 생긴 후 데이터가 저장됐겠지만 코드가 종료되어 container 가 종료되는 순간 데이터도 같이 사라지게 된다. 

 

이때 bind mount를 활용하여 로컬에 있는 data 폴더와 docker 내부에 있는 data 폴더를 마운트 시켜줄 수 있는 것이다!

 

🤔 bind mount 하는 방법

docker run 커맨드를 실행할 때, -v 옵션을 이용해 콜론 앞부분에 호스트의 경로를 지정해 주면 된다. 

$ docker build . -t volume:test; docker run -v `pwd`/data/:/app/data/ -d --name vol -p 8000:8080 volume:test

즉, docker 가 실행됨에 따라 local에 있는 data 폴더 내부에 test.txt를 생성해서 그곳에 데이터를 저장한다. 즉 Host의 디렉터리에 직접 Access 한다. 사실 로컬에서 테스트할 때는 bind mount 로도 충분하다고 한다. 

 

 

2. Volume

Volume의 경우 bind mount 보다 좀 더 좁은 범위의 마운트이며, 도커에 의해 관리되는 영역에 데이터가 저장된다. 

위의 그림을 다시 가져와서 보면 bind mount의 경우 전체 Filesystem 이 컨테이너에 마운트 되는 형태였다면 volume의 경우 격리된 별도의 저장공간을 만든 후, 필요할 때 마운트 하는 형식이다. 

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

Volume 방식이 Docker에서 더 권장하는 방식이다. 그럴 수밖에 없는 게 bind mount의 경우 사용자의 소유자와 권한 때문에 실행 및 수정에 문제가 있을 수 있어 보안에 취약하다. 위에서 보다시피 전체 File System에 접근하는 것만 봐도 그 이유를 알 수 있다. 

 

그렇다면 이 Volume을 어떻게 생성하고 마운트 시키는지 알아보자.

 

볼륨 생성

$ docker volume create volume-test

 

볼륨 확인

$ docker volume ls

DRIVER    VOLUME NAME
local     volume-test

 

볼륨 마운트하기

$ docker build . -t volume:test; docker run -v volume-test:/app/data/ -d --name vol -p 8000:8080 volume:test

 

마운트 확인

$ docker inspect vol

"Mounts": [
            {
                "Type": "volume",
                "Name": "volume-test",
                "Source": "/var/lib/docker/volumes/volume-test/_data",
                "Destination": "/app/data",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ]

 

/var/lib/docker/volumes/volume-test/_data에 source 가 잘 설정되어 있는 것을 볼 수 있다. 

 

하지만 Mac에서 /var/lib/docker 내부로 들어가서 직접 확인하려고 하니

/var/lib/docker not found in mac 다음과 같은 에러가 발생했다. 이 부분에 대해선 다음에 다시 자세히 찾아보고 정리해 두도록 하겠습니다. 

 

또한 볼륨의 경우 다른 컨테이너에서도 volume-test volume에 마운트가 가능하다. 따라서 데이터를 서로 공유할 수 있는 것이다.

 

볼륨 삭제

$ docker volume rm volume-test

 

 


오늘은 이전부터 계속 대충 개념만 알고 있던 docker의 마운트 개념에 대해서 학습해 보고 실습해 보았다. 확실히 실습을 해야 잘 와닿는 것 같다. 즉, 볼륨과 바인드 마운트의 공통점은 모두 지정한 위치에 파일을 생성할 수 있고, 공유할 수 있고, 수정할 수 있다는 것이다. 

 

하지만 차이점이라고 한다면 볼륨으로 생성할 경우 Docker 가 관리하는 Directory 내에 생성이 된다는 것, 또한 바인드 마운트 같은 경우 파일 시스템에 직접 접근하기 때문에 보안상 문제가 있을 수 있다는 것, 따라서 간단한 로컬 테스트에서 사용하면 편하다는 것이다. 

728x90
반응형

댓글