docker

도커 컨테이너 다루기(3) - 도커 볼륨

말랑Cow 2021. 5. 25. 00:00
반응형

도커 이미지로 컨테이너를 생성하면 이미지는 Read-Only 가 되며 컨테이너의 변경사항만 별도로 저장해서 각 컨테이너 정보를 보존합니다.

즉, 이미 생성된 이미지는 어떠한 경우로도 변경되지 않으며 컨테이너 계층에다가 원래 이미지에서 변경 된 파일시스템 등을 저장합니다.

 

만약 A라는 컨테이너를 삭제하면 컨테이너 계층에 저장돼있던 정보도 삭제됩니다.

도커 컨테이너는 생성/삭제가 매우 간단하므로 컨테이너 삭제 시 데이터를 복구할 수 없게 됩니다.

이를 방지하기 위해 컨테이너의 데이터를 영속적(Persistent) 데이터로 활용할 수 있는 방법이 몇 가지 있습니다.

 

1. 호스트 볼륨 공유


[root@localhost test1]# docker run -d --name hostvol_test -e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=test -v /home/test1:/var/lib/mysql mysql:5.7
7e0a030d01622a2dd81ade50252cae8e2f012f2a78779e031d21c143861fc9e4
[root@localhost test1]# ll /home/test1/
합계 122944
-rw-r-----. 1 polkitd input       56  5월 24 09:56 auto.cnf
-rw-------. 1 polkitd input     1676  5월 24 09:56 ca-key.pem
-rw-r--r--. 1 polkitd input     1112  5월 24 09:56 ca.pem
-rw-r--r--. 1 polkitd input     1112  5월 24 09:56 client-cert.pem
-rw-------. 1 polkitd input     1680  5월 24 09:56 client-key.pem
-rw-r-----. 1 polkitd input 50331648  5월 24 09:56 ib_logfile0
-rw-r-----. 1 polkitd input 50331648  5월 24 09:56 ib_logfile1
-rw-r-----. 1 polkitd input 12582912  5월 24 09:56 ibdata1
-rw-r-----. 1 polkitd input 12582912  5월 24 09:56 ibtmp1
drwxr-x---. 2 polkitd input     4096  5월 24 09:56 mysql
drwxr-x---. 2 polkitd input     8192  5월 24 09:56 performance_schema
-rw-------. 1 polkitd input     1680  5월 24 09:56 private_key.pem
-rw-r--r--. 1 polkitd input      452  5월 24 09:56 public_key.pem
-rw-r--r--. 1 polkitd input     1112  5월 24 09:56 server-cert.pem
-rw-------. 1 polkitd input     1680  5월 24 09:56 server-key.pem
drwxr-x---. 2 polkitd input     8192  5월 24 09:56 sys
[root@localhost test1]# docker stop hostvol_test
hostvol_test
[root@localhost test1]# docker rm hostvol_test
hostvol_test
[root@localhost test1]# ll /home/test1/
합계 176196
-rw-r-----. 1 polkitd input       56  5월 24 09:56 auto.cnf
-rw-------. 1 polkitd input     1676  5월 24 09:56 ca-key.pem
-rw-r--r--. 1 polkitd input     1112  5월 24 09:56 ca.pem
-rw-r--r--. 1 polkitd input     1112  5월 24 09:56 client-cert.pem
-rw-------. 1 polkitd input     1680  5월 24 09:56 client-key.pem
-rw-r-----. 1 polkitd input      694  5월 24 09:57 ib_buffer_pool
-rw-r-----. 1 polkitd input 50331648  5월 24 09:57 ib_logfile0
-rw-r-----. 1 polkitd input 50331648  5월 24 09:56 ib_logfile1
-rw-r-----. 1 polkitd input 79691776  5월 24 09:57 ibdata1
drwxr-x---. 2 polkitd input     4096  5월 24 09:56 mysql
drwxr-x---. 2 polkitd input     8192  5월 24 09:56 performance_schema
-rw-------. 1 polkitd input     1680  5월 24 09:56 private_key.pem
-rw-r--r--. 1 polkitd input      452  5월 24 09:56 public_key.pem
-rw-r--r--. 1 polkitd input     1112  5월 24 09:56 server-cert.pem
-rw-------. 1 polkitd input     1680  5월 24 09:56 server-key.pem
drwxr-x---. 2 polkitd input     8192  5월 24 09:56 sys
drwxr-x---. 2 polkitd input       20  5월 24 09:56 test

-v 옵션을 주어 호스트의 /home/test1 디렉토리와 컨테이너의 /var/lib/mysql 을 연결, 즉 공유설정 하였습니다.

 

위 예시의 경우 호스트에는 /home/test1 디렉토리가 존재하지 않았으나 -v 옵션으로 공유설정 후에 디렉토리가 생성됐고 이 디렉토리에 파일이 공유되었습니다.(컨테이너의 파일이 호스트로 복사)

 

이후 컨테이너를 삭제한 후 호스트의 /home/test1 디렉토리 확인해보니 컨테이너는 삭제됐지만 데이터는 그대로 남아있는것을 확인할 수 있습니다.

 

이것은 디렉토리 끼리 동기화가 되는 것이 아닌 완전히 같은 디렉토리가 되는 것 입니다.

 

디렉토리 단위의 공유 뿐 아니라 단일 파일 단위의 공유도 가능하며, 동시에 여러 -v 옵션을 쓸 수 있습니다.

 

만약 호스트에 이미 디렉토리와 파일이 존재하고 컨테이너에도 존재할 때 두 디렉토리를 공유한다면 컨테이너의 디렉토리 자체가 덮어씌워집니다.(이미지에 원래 존재하던 파일이 없어지고 호스트에서 공유된 파일이 존재하게 됨)

즉, 호스트의 디렉토리가 컨테이너의 디렉토리에 마운트 되는 개념입니다.

 

 

2. 볼륨 컨테이너


컨테이너 생성 시 --volumes-from 옵션을 설정하면 -v 나 --volume 옵션을 적용한 컨테이너의 볼륨 디렉토리를 공유할 수 있습니다. ( 직접 볼륨을 공유하는 것이 아닌 -v 옵션을 적용한 컨테이너를 통해 공유하는 것 )

 

[root@localhost ~]# docker run -t -i --name test --volumes-from test1 ubuntu:18.04

위 예시는 test1 이라는 컨테이너의 볼륨 디렉토리를 공유하는 것 입니다.

 

3. 도커 볼륨


[root@localhost ~]# docker volume create --name myvolume
myvolume
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     myvolume

위와 같이 myvolume 이라는 볼륨을 생성하였으며 생성된 볼륨을 확인하였습니다.

 

[root@localhost ~]# docker run -t -i --name myvolume_1 -v myvolume:/root/ ubuntu:18.04
root@409f23977ef2:/# echo hello >> /root/volume


[root@localhost ~]# docker run -t -i --name myvolume_2 -v myvolume:/root/ ubuntu:18.04
root@fecc14532a0e:/# cd /root/
root@fecc14532a0e:~# ll
total 16
drwx------. 2 root root   72 May 24 01:38 ./
drwxr-xr-x. 1 root root    6 May 24 01:38 ../
-rw-------. 1 root root   42 May 24 01:38 .bash_history
-rw-r--r--. 1 root root 3106 Apr  9  2018 .bashrc
-rw-r--r--. 1 root root  148 Aug 17  2015 .profile
-rw-r--r--. 1 root root    6 May 24 01:38 volume

myvolume을 /root 디렉토리에 마운트했으며 /root/volume 이라는 파일이 myvolume 이라는 볼륨에 저장됩니다.

이후 myvolume_2 라는 컨테이너를 myvolume 이라는 볼륨을 써서 생성한 후 root 디렉토리 확인 시 위에서 생성했던 /root/volume 파일을 확인할 수 있습니다.

 

도커 볼륨도 호스트 볼륨과 마찬가지로 호스트에 저장함으로써 데이터를 보존합니다.

 

[root@localhost ~]# docker inspect --type volume myvolume
[
    {
        "CreatedAt": "2021-05-24T10:38:37+09:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/myvolume/_data",
        "Name": "myvolume",
        "Options": {},
        "Scope": "local"
    }
]

위 명령으로 myvolume 이라는 볼륨이 호스트의 어느위치에 마운트 되었는지 확인할 수 있습니다.

 

--mount type=volume,source=myvolume,target=/root

-v 옵션을 위와같이 사용할 수도 있습니다.

 

--mount type=bind,source=/home/test,target=/home/test1

볼륨이 아닌 호스트의 특정 디렉토리를 컨테이너 내부에 마운트하는 경우에는 type을 bind로 하여 설정할 수 있습니다.

 

* stateless : 컨테이너가 아닌 외부에 데이터를 저장하고 컨테이너는 그 데이터로 동작하도록 설계

* stateful : 컨테이너가 데이터를 저장하고 있는 상태

반응형