Volume & Bind Mount
- Docker 컨테이너(Container)에 쓰여진 데이터는 기본적으로 컨테이너가 삭제될 때 함께 사라지게 됨
- 하지만 Docker에서 돌아가는 많은 애플리케이션은 컨테이너의 생명 주기와 관계없이 데이터를 영속적으로 저장을 해야함
- 뿐만 아니라 많은 경우 여러 개의 Docker 컨테이너가 하나의 저장 공간을 공유해서 데이터를 읽거나 써야함
- 이렇게 Docker 컨테이너의 생명 주기와 관계없이 데이터를 영속적으로 저장할 수 있도록 Docker는 두가지 옵션을 제공
- 첫번째는 볼륨(Volume)
- 두번째는 바인드 마운트(Bind Mount)
볼륨
볼륨 생성 및 조회
- Docker에서 권장하는 방법인 볼륨(volume)
docker volume create
커맨드를 이용해서 볼륨 생성
- 그 다음
docker volume ls
커맨드를 실행하면 생성한 볼륨을 확인할 수 있음
docker volume inspect
커맨드를 통해 해당 볼륨을 좀 더 상세한 정보를 확인해볼 수 있음
Mountpoint
항목을 보면 해당 볼륨이 컴퓨터의 어느 경로에 생성되었는지를 알 수 있음
$ docker volume create our-vol
our-vol
$ docker volume ls
DRIVER VOLUME NAME
local our-vol
$ docker volume inspect our-vol
[
{
"CreatedAt": "2020-05-09T17:03:46Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/our-vol/_data",
"Name": "our-vol",
"Options": {},
"Scope": "local"
}
]
볼륨을 컨테이너에 마운트하기
- 컨테이너가 볼륨을 사용하기 위해서는 볼륨을 컨테이너에 마운트(mount)해줘야 함
docker run
커맨드로 컨테이너를 실행할 때 -v
옵션을 사용하면 되는데 콜론(:
)을 구분자로 해서 앞에는 마운트할 볼륨명 뒤에는 컨테이너 내의 경로를 명시해주면 됨
- 예를 들어,
our-vol
볼륨을 one
컨테이너의 /app
경로에 마운트를 할 수 있음
touch /app/test.txt
커맨드를 실행하면 test.txt
파일이 our-vol
볼륨의 경로에도 남아있을 것
docker inspect
커맨드로 컨테이너의 상세 정보를 확인해보면 our-vol
볼륨이 volume
타입으로 마운트되어 있는 것을 확인할 수 있음
$ docker run -v our-vol:/app --name one busybox touch /app/test.txt
$ ls /var/lib/docker/volumes/our-vol/_data
test.txt
$ docker inspect one
(...생략...)
"Mounts": [
{
"Type": "volume",
"Name": "our-vol",
"Source": "/var/lib/docker/volumes/our-vol/_data",
"Destination": "/app",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
(...생략...)
볼륨을 다른 컨테이너에도 마운트하기
- 같은
our-vol
볼륨을 two
컨테이너의 /app
경로에 마운트를 할 수 있음
ls /app
커맨드를 실행해보면 one
컨테이너가 볼륨에 생성해놓은 파일이 그대로 보이는 것을 알 수 있음
$ docker run -v our-vol:/app --name two busybox ls /app
test.txt
- 이렇게 여러 개의 컨테이너가 하나의 볼륨에 접근할 수 있기 때문에 컨테이너 간 데이터 공유가 가능
- 다시 말해, 어떤 볼륨에 데이터를 저장해두고 여러 컨테이너에 마운트만 해주면 해당 데이터를 모든 컨테이너에서 접근할 수 있게 됨
볼륨 삭제
docker volume rm
커맨드를 사용해서 our-vol
볼륨 제거 가능
$ docker volume rm our-vol
Error response from daemon: remove our-vol: volume is in use - [f73130c9dad14644ac46b89fe4018e561a7bcbfa4118d637949642d0d5d742e4, 666dda54f6be8ca852f3150b9741a9cab5a4659fa2e83fe6ca339550072c861ex]
- 위와 같이 제거하려는 볼륨이 마운트되어 있는 컨테이너가 있을 때는 해당 볼륨이 제거가 되지않음
- 그럴 때는 해당 볼륨이 마운트되어 있는 모든 컨테이너를 먼저 삭제하고 볼륨을 삭제해야 함
$ docker rm -f one two
one
two
$ docker volume rm our-vol
our-vol
볼륨 청소
docker 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
바인드 마운트
바인드 마운트란?
- Docker 컨테이너에 데이터를 저장하기 위한 다른 방법으로 바인드 마운트(Bind Mount)라는 것도 있음
- 바인드 마운트를 사용하면 호스트 파일 시스템의 특정 경로를 컨테이너로 바로 마운트할 수 있음
- 바인드 마운트를 사용하는 방법은
docker run
커맨드를 실행할 때, -v
옵션의 콜론(:
) 앞 부분에 마운트명 대신에 호스트의 경로를 지정
- 예를 들어, 현재 경로에
test.txt
파일을 생성하고 해당 호스트 경로를 컨테이너의 /app
경로에 마운트 가능
- 컨테이너에 터미널을 붙여서
ls /app
커맨드를 실행해보면 test.txt
파일이 컨테이너의 /app
경로에도 존재하는 것을 확인할 수 있음
- 반대로 컨테이너의
/app
경로 상에서 test2.txt
파일을 실행해보면 호스트의 현재 경로에도 해당 파일이 보이는 것을 알 수 있음
docker inspect
커맨드로 해당 컨테이너의 상세 정보를 확인해보면 현재 경로(/root
)가 bind
타입으로 마운트되어 있는 것을 확인할 수 있음
$ touch test.txt
$ docker run -v `pwd`:/app -it --name one busybox /bin/sh
/
test.txt
/
/
[node1] (local) root@192.168.0.18 ~
$ ls
test.txt test2.txt
$ docker inspect one
(...생략...)
"Mounts": [
{
"Type": "bind",
"Source": "/root",
"Destination": "/app",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
(...생략...)
볼륨 VS 바인드 마운트
- 볼륨(Volume)과 바인드 마운트(Bind Mount)의 가장 큰 차이점은 Docker가 해당 마운트 포인트를 관리해주느냐 안 해주느냐에 달려있음
- 볼륨을 사용할 때는 우리가 스스로 볼륨을 생성하거나 삭제해야하는 불편함이 있지만, 해당 볼륨은 Docker 상에서 이미지(Image)나 컨테이너(Container), 네트워크(Network)와 비슷한 방식으로 관리가 되는 이점이 있음
- 그래서 대부분의 상황에서는 볼륨을 사용하는 것이 권장되지만 컨테이너화된 로컬 개발 환경을 구성할 때는 바인드 마운트가 더 유리할 수 있음
- 로컬에서 개발을 할 때는 일반적으로 현재 작업 디렉터리에 프로젝트 저장소를
git clone
받아놓고 코드를 변경
- 따라서 바인드 마운트를 이용해서 해당 디렉터리를 컨테이너의 특정 경로에 마운트 해주면 코드를 변경할 때 마다 변경 사항을 실시간으로 컨테이너를 통해 확인할 수 있음
- 반대로 컨테이너를 통해 변경된 부분도 현재 작업 디렉터리에도 반영이 되기 때문에 편리