도커의 컨테이너안에 데이터를 저장할 수 있지만 여기에는 몇 가지 문제점이 존재한다.

1. 컨테이너가 삭제되면 데이터도 삭제된다. 
2. 다른 프로세스에서 특정 컨테이너에 저장된 데이터를 사용하기 어렵다.
3. 컨테이너에 데이터를 저장하기 위해서는 파일시스템을 관리하는 스토리지 드라이버가 필요하다.

   그러나 이 기능은 호스트 파일시스템에 직접 쓴는 것보다 성능이 떨어진다.

따라서 이러한 문제를 해결하기 위해 여러가지 방법이 있는데, 그 중 2가지 방법을 알아본다. 첫번째는 호스트 서버의 경로와 컨테이너의 경로를 연결하는 방식, 두번째는 docker volume을 생성해서 연결하는 방식이다.

 

 

* 호스트 서버의 경로와 컨테이너의 경로를 연결

- docker container run -v 옵션을 사용해서 호스트의 디렉토리와 마운트될 컨테이너의 디렉토리를 명시할 수 있다.

 

 

1. 호스트 디스크를 명시하지 않고 생성

컨테이너에서 -v 명령에서 명시될 디렉토리들은 없으면 알아서 만들어진다. (따라서 미리 만들 필요가 없다) 

- 아래 예시는 한 컨테이너 안에 2개의 마운트 포인트를 만드는 것이다.

- 이 마운트 포인트는 호스트 서버의 /var/lib/docker/volumes에 저장된다. 컨테이너가 삭제되어도 해당 데이터는 남아있다.

- 호스트 디스크는 도커 디렉토리 (/var/lib/docker/volumes) 에 저장되므로, 해당 디렉토리 파티션의 용량이 한도가 된다.

docker run -it --name data_share -v /data_dir -v /test_dir ubuntu /bin/bash

- 참고로, 컨테이너 안에서 df -h 쳤을 때 마운트 포인트가 2개가 나와야 하는데, 하나만 나온다. 2개가 실제로는 있다.

- mount 명령으로 확인하면, 잘 마운트 되어있는 것을 확인할 수 있다.

 

- 호스트에서 해당 컨테이너의 마운트 정보를 보려면 다음과 같이 입력한다.

docker inspect --format="{{ .HostConfig.Binds }}" data_share

 

2. 호스트 디스크를 명시하고 생성

- 호스트 디스크를 따로 명시하므로, 해당 디스크가 외장 스토리지가 될 수도 있고, 다른 내부 저장공간이 될 수도 있다.

- -v 옵션이후 호스트와 컨테이너 디렉토리는 없으면 알아서 만들어진다. 따라서 둘 다 일부러 따로 만들 필요가 없다.

- 이렇게 하면 호스트에 /test1 /test2를 만들어서 각각 컨테이너의 /data_dir, /test_dir 에 마운트된다.

docker run -it --name data_share -v /test1:/data_dir -v /test2:/test_dir ubuntu /bin/bash

- 호스트의 /test1, /test2는 외장 스토리지나 NFS 등 여러방식으로 외장 스토리지가 될 수 있다.

 

# 참고 : 디스크 마운트 설정 시ro/rw 옵션 외 기타 옵션 넣기

docker run -it --name data_share -v /test1:/data_dir:ro -v /test2:/test_dir:rw ubuntu /bin/bash

또한, --volume = host:container1:container2 이런식으로 다중컨테이너에 연결 가능

 

다른 옵션들은 더 이상 자세한 설명은 생략한다.

 

 

 

* docker volume을 구성해서 컨테이너에 연결

docker volume은 따로 docker에서 관리하는 형태로 호스트에 volume을 생성하며, 해당 볼륨은 docker volume ls 등으로 리스트를 확인할 수 있다.  따라서 관리하는 측면에서 훨씬 유용하다. 또한 volume이 저장되는 공간만 외장 스토리지로 마운트하여 대용량으로 사용할수도 있다.

 

도커 volume은 /var/lib/docker/volumes 경로에 저장된다.  또한 각 데이터는 /var/lib/docker/volumes/볼륨명/_data 밑에 저장된다. 이러한 volume 들은 컨테이너가 삭제되어도 그대로 유지된다. 또한 다른 컨테이너에서 다시 마운트하면 해당 데이터를 볼 수 있다.

 

 

1. docker volume 명령 리스트

< 도커 기본 명령어 차례 >

 

● 시스템 명령

docker version

docker system info

docker system df

docker system prune

docker login

locker logout

 

● 이미지 관리 명령

docker pull

docker image ls

docker images

docker image inspect

docker image tag

docker push

docker search

docker image rm

docker image prune

docker container commit

 

● 컨테이너 실행 및 조작 관련 명령

docker container create

docker container run

docker container attach

docker container exec

 

● 컨테이너 정보 확인 명령

docker container ps

docker container stats

docker container inspect

docker container top

docker container port

docker container diff

docker container logs

docker container ls

 

● 컨테이너 관리 명령

docker container stop

docker container start

docker container kill

docker container restart

docker container prune

docker container pause

docker container unpause

docker container rename

docker container cp

 

● 컨테이너/이미지 백업 명령

docker container export

docker container import

docker image save

docker image load

 

● 네트워크 명령

docker network ls

docker network create

docker network connect

docker network disconnect

docker networkinspect

docker network rm

brctl show

 

● 볼륨 명령 
docker volume create 
docker volume ls 
docker volume rm 
docker volume prune 
docker volume inspect


 

docker volume create  볼륨명

- docker에서 사용할 volume을 생성한다. 볼륨명을 명시하지 않으면, random한 이름으로 생성된다.

 

 

docker volume ls 

- 현재 생성되어 있는 모든 볼륨을 보여준다.

- 긴 이름으로 된 볼륨들은 위에서 수행한 "호스트 디스클를 명시하지 않고 생성하거나, 볼륨 생성시 따로 이름을 주지 않은 것들이다.

 

 

docker volume rm  볼륨명

- 현재 존재하는 볼륨을 삭제한다.

 

 

 

docker volume prune

- 사용하지 않는 모든 볼륨을 지울 수 있다. 

 

 

docker volume inspect 볼륨명

- volume의 상세 정보를 확인할 수 있다.

 

# 참고 : 컨테이너가 가지고 있는 볼륨을 확인하기

- docker inspect data_share | grep -i volumes

 

 

2. docker volume을 이용하여 컨테이너 생성하기

run -it --name disk-test -v test-volume:/test ubuntu /bin/bash 

 

 

 

* 동일 디스크 정보를 그대로 공유받기

- 생성된 볼륨이나 파일시스템들은 동시에 볼륨을 여러 컨테이너에 마운트할  수 있다. 아래와 같이 --volumes-from 옵션을 사용할 수 있다.

- 아래 명령은 맨 처음에 만든 data_share 라는 이름의 컨테이너가 가진 볼륨 정보를 그대로 공유받아서 마운트한다. 

docker run -d -it --name disk-test-share --volumes-from data_share  ubuntu /bin/bash

또 새롭게 컨테이너를 만들어서, 예를들어 이름을 disk-test-share2 하고 똑같은 data_share의 볼륨을 "공유" 받을 수 있다. 이렇게 하면 아래와 같은 형식이 될 것이다. 

 

 

 

* 오버레이 파일시스템 드라이버

overlay는 도커에서 사용하는 파일시스템 드라이버이다. 더 이상 자세한 설명은 생략한다. 컨테이너를 만들고 호스트에서 df -h를 쳤을 때 overlay 라고 마운트되어있는 것은 각 컨테이너의 루트디렉토리이다. 즉 /var/lib/docker/overlay2 에는 각 컨테이너의 루트 디렉토리, /var/lib/docker/volumes 에는 생성한 볼륨이 들어간다. 

 

호스트에서 df -h 를 쳤을 때. 아래 overlay라고 써있는 것이 도커 컨테이너들의 루트이다. 

또한 해당 데이터는 마운트 포인트인 /var/lib/docker/overlay2/이름/merged 디렉토리에 저장된다. 들어가보면 루트 파일시스템 같은 모양을 확인할 수 있을 것이다. 컨테이너가 삭제되면, 이 오버레이 마운트 경로의 데이터는 모두 삭제된다.

컨테이너에서 df -h를 쳤을 때. overlay 부분이 / 인 것을 확인할 수 있다.

 

# 참고 : 컨테이너 내에서 lsblk, blkid 명령은 제대로 나오지 않는다.

 

 

* -v 대신 사용하는 --mount 옵션

위에서 언급한대로 독립형 컨테이너에서는 -v / --volume이 사용되며, 도커 스웜 모드에서는 --mount가 사용된다.  이후 도커 17.06 부터 --mount를 독립형 컨테이너에서 사용할 수 있게 되었다. 따라서 -v 옵션 외에 --mount 옵션도 쓸 수 있다. 특히 특정 볼륨 드라이버를 명시해서 사용할 때는 --mount를 사용해야 한다. 


--mount 옵션은 쉼표(,)로 구분되고 각각 여러 key-value 쌍으로 구성된다. --mount 구문은 -v 또는 --volume보다 길지만, key의 순서는 중요치 않으며 Flag의 값을 이해하기 쉽게 되어있다.

 

예시

docker run -d -it --name=nginxtest --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly nginx:latest

- type : mount의 유형을 지정한다. (bind, volume,tmpfs)

- source(src) : volume의 이름. 익명 볼륨을 사용한다면 생략해도 된다.

- destination(dst,target) : 컨테이너에 마운트 될 경로

- readonly : 컨테이너에 읽기 전용으로 마운트됨

opt 등 여러 추가 옵션이 있으나 더 이상 자세한 설명은 생략한다.

 

 

 

 

* 추가 예시 : dd로 디스크 img 파일을 만들어 할당하기

 

1. disk 파일 생성

dd if=/dev/zero of=파일명 count=512 bs=1M

 

2. 해당 이미지 파일로 파일시스템 생성

mkfs.ext4 harddrive.img

 

3. 호스트 서버에서 테스트 디렉토리 생성 후 마운트

mkdir /test
mount /harddrive.img /test

 

4. 도커 컨테이너를 만들고 해당 파일시스템을 참조시킨다.

docker run -it -v /test:/container_dr ubuntu /bin/bash

 

5. 컨테이너 상에서 확인. 파일시스템의 사이즈와 안에 있는 데이터를 확인할 수 있다.

df -h

 

+ Recent posts