Docker의 Storage 부분을 공부하다가 Volume과 Bind Mount가 헷갈려 정리하기 위해 적는 글 입니다.
혹시 틀린 부분이 있다면 지적해주시면 감사하겠습니다 : )
Docker 컨테이너에 쓰여지는 데이터는 기본적으로 컨테이너가 삭제될 때 같이 삭제된다. Docker 컨테이너 특성상 삭제하고 생성하는 일이 잦기 때문에 많은 어플리케이션은 컨테이너 주기와 상관없이 데이터를 영속적으로 저장할 필요가 있다. 혹은, 여러 개의 Docker 컨테이너가 하나의 저장 공간을 공유해서 데이터를 읽거나 쓸 수 도 있다.
따라서, Docker의 컨테이너 생명 주기와 관계없이 데이터를 영속적으로 저장할 수 있도록 Docker는 아래 2가지 옵션을 제공한다.
- Volume (볼륨)
- Bind Mount (바인드 마운트)
가장 큰 차이는 데이터가 어디에 저장되는가! 이다. 아래 내용을 살펴보자.
1. Volume (볼륨)
- Docker에서 생성/삭제 등 완전히 관리
- Docker engine을 통해 사용할 수 있는 볼륨을 생성하여 사용함 (명칭 및 폴더 지정 가능 / docker volume create 로 생성)
- 실제 생성된 볼륨은 Host의 /var/lib/docker/volumes 하위에 볼륨 이름의 경로를 생성하여 저장 (Docker Host의 디렉토리에 저장됨 -> Host와는 분리)
- 여러 컨테이너에 동시에 마운트할 수 있음
volume 생성하기
$ docker volume create myvol
myvol
volume 조회하기
$ docker volume ls
DRIVER VOLUME NAME
local myvol
volume 상세 정보 조회
: Mountpoint가 /var/lib/docker/volumes 폴더 하위에 본인이 생성한 볼륨명/_data인 것을 확인할 수 있다.
$ docker volume inspect myvol
[
{
"CreatedAt": "2022-06-08T17:00:47+09:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/myvol/_data",
"Name": "myvol",
"Options": {},
"Scope": "local"
}
]
/var/lib/docker/volumes/myvol/_data 경로 확인하기
: 현재 아무 파일도 존재하지 않음
$ ls /var/lib/docker/volumes/myvol/_data
volume을 컨테이너에 마운트하기
컨테이너가 볼륨을 사용하기 위해서는 볼륨을 컨테이너에 마운트해주는 과정이 필요하다. (연결시켜준다고 이해하면 된다.)
docker run 커맨트로 컨테이너를 실행할 때 -v 옵션을 통해 mount한다. 콜론(:)을 사용하여 앞에는 마운트할 볼륨명 / 뒤에는 컨테이너 내의 경로를 명시하면 된다.
아래는 myvol 볼륨을 test 컨테이너의 /app 경로에 마운트 한 것이다.
(이런 방식으로 컨테이너명만 바꿔서 컨테이너를 생성하면, 여러 개의 컨테이너가 하나의 볼륨을 공유하게 된다.)
$ docker run -v myvol:/app --name test busybox touch /app/test.txt
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
19d511225f94: Pull complete
Digest: sha256:3614ca5eacf0a3a1bcc361c939202a974b4902b9334ff36eb29ffe9011aaad83
Status: Downloaded newer image for busybox:latest
touch /app/test.txt 명령어를 통해 myvol 볼륨의 경로에 파일이 생성됐는지 확인해본다.
(* touch 명령어는 리눅스에서 파일의 생성과 갱신하는 명령어이다.)
/var/lib/docker/volumes/myvol/_data 경로 확인하기
$ ls /var/lib/docker/volumes/myvol/_data
test.txt
생성한 test container 상세 정보 조회
myvol 볼륨이 volume 타입으로 마운트되어있는 것을 확인할 수 있다.
$ docker inspect test
..생략
"Mounts": [
{
"Type": "volume",
"Name": "myvol",
"Source": "/var/lib/docker/volumes/myvol/_data",
"Destination": "/app",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
volume 삭제하기
$ docker volume rm myvol
Error response from daemon: remove myvol: volume is in use - [96b4190169ad8cd341b18a39e072598db39140862f85cbcdfb706bf6f986b1c6, 7ae45fe80e112f666c3dc13d41c7ab415e41a1ea5e8b110d8f92a265a781c505]
볼륨은 바로 지워지지 않는다. 에러 내용을 보면 사용중인 볼륨이라고 뜬다.
해당 볼륨이 마운트되어있는 모든 컨테이너는 삭제하고, 볼륨을 삭제하면 정상적으로 삭제된다.
$ docker rm -f test test1
test
test1
$ docker volume rm myvol
myvol
마운트되어있지 않은 놀고있는 모든 volume 삭제하기
prune 은 마운트되어 있지 않은 모든 볼륨을 한 번에 삭제할 수 있다.
$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
2. Bind Mount (바인드 마운트)
- Volume과 다르게 호스트 파일 시스템의 특정 경로를 컨테이너로 바로 마운트
- 사용 방법은 docker run 커맨드 실행 시, -v 옵션으로 콜론(:) 앞 부분에 마운트명 대신에 호스트의 경로를 지정해줌
- Host의 File System 디렉토리 구조에 의존적
- Docker CLI 명령어로 Bind Mount 관리 불가
Bind Mount 실습에 사용될 파일 생성
: 현재 경로(/test) 에 test.txt 파일 생성
$ mkdir test # 테스트할 폴더 생성
$ cd test/ # 기존에 빈 폴더
$ ls
$ touch test.txt #test.txt 파일 생성
$ ls
test.txt
바인드 마운트를 통한 컨테이너 생성
: 해당 호스트 경로를 컨테이너의 /app 경로에 마운트하여 터미널로 /app 경로 확인하면 test.txt 파일이 컨테이너의 /app 경로에도 존재하는 것을 확인할 수 있다.
생성한 컨테이너의 /app 경로에서 파일 생성하기
/ # touch /app/test2.txt
/ # ls /app
test.txt test2.txt
/ # exit
호스트 경로에서 파일 확인
: 컨테이너의 /app 경로상에서 생성한 test2.txt 파일이 호스트의 현재경로에도 보이는 것을 확인할 수 있음.
컨테이너 상세 정보 확인하기
: 해당 컨테이너의 상세 정보 확인해보면 현재 경로("/home/loginid/test")가 bind type으로 마운트되어 있을 것을 확인 할 수 있음
$ docker inspect test
..생략
"Mounts": [
{
"Type": "bind",
"Source": "/home/loginid/test",
"Destination": "/app",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
Volume(볼륨) vs Bind Mount (바인드 마운트)
볼륨과 바인드 마운트의 가장 큰 차이는 Docker가 해당 마운트 포인트를 관리하는지/안하는지 이다. 볼륨의 경우 생성 및 삭제를 사용자가 해야한다는 불편함도 있지만, 이미지/컨테이너 등과 같이 관리가 가능한 이점도 있어 대부분의 상황에서는 볼륨을 사용하는 것이 권장된다.
볼륨의 장점으로는?
- 바인드 마운트보다 백업 또는 마이그레이션이 쉽다.
- CLI 명령이나 Docker API를 사용해 관리할 수 있다.
- OS에 구애받지 않는다.
- 여러 Container간에 데이터를 안전하게 공유할 수 있다.
- 볼륨 드라이버를 사용하면 볼륨의 내용을 암호화하거나 다른 기능을 추가할 수 있다.
- Container의 용량을 늘리지 않고 데이터를 저장할 수 있다.
3. tmpfs mount (tmpfs 마운트)
임시 데이터이며, host의 메모리에서만 지속된다. 컨테이너가 중지되면 tmpfs 마운트가 제거되고, Memory에 작성된 파일 또한 제거된다. 또한, 컨테이너간 공유가 불가하다.
참고 사이트