Simple is IT, 누구나 보고 누구나 깨닫는 IT

도커 볼륨으로 효율적인, Stateless한 Container 운영을 해보자! 본문

Simple is IT/Cloud & Container

도커 볼륨으로 효율적인, Stateless한 Container 운영을 해보자!

currenjin 2020. 7. 16. 21:42

Docker Volume

우리는 도커를 사용하면서 약간의 불편함을 겪었어요.

너무나도 간편하게 컨테이너를 생성하고 지울 수 있는 도커이지만 실수로 삭제했을 때는 복구가 불가능하다는 것이죠.

 

왜요?.. 자세하게 설명해주세요!

도커 이미지로 컨테이너를 생성하면 해당 이미지는 읽기 전용이 돼요. 이 때는 컨테이너의 변경 사항들만 별도로 저장해서 각 컨테이너의 정보를 보존하죠.

예를 들어, 우리가 httpd 이미지로 컨테이너를 생성했을 때 웹에 대한 접속 로그는 httpd 컨테이너에 남게 되는 것처럼 말이에요.

 

이 구성은 아래 그림과 같은 구조를 연상시킨답니다.

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

 

하지만 아까 언급했던 것처럼 컨테이너를 삭제하면 컨테이너 계층에 있던 모든 파일과 정보가 사라진다는 점이 가장 치명적인 단점이죠.

이 상황을 방지하기 위해 컨테이너의 데이터를 영속적(Persistent) 데이터로 활용할 수 있는 방법이 있어요.

 그 중 가장 활용하기 쉬운 방법이 볼륨을 활용하는 것이랍니다.

 


Docker에서 사용하는 볼륨의 종류

  • Host Volume 공유

  • Volume Container

  • Docker Volume

 

Host Volume 공유

다음 명령어로 웹 컨테이너를 생성해보아요.

docker run -d --name web_hostvolume \
-p 80:80 \
-v ~/test_hostvolume:/usr/test_hostvolume \
httpd

-p 옵션으로 컨테이너의 웹 포트를 호스트 80번 포트로 매핑시켰으므로 호스트 IP를 통해 웹접속을 할 수 있어요.

 

여기서 포인트는 -v 옵션이에요.

-v [호스트의 공유 디렉토리]:[컨테이너의 공유 디렉토리]

즉, 호스트의 ~/test_hostvolume 디렉토리와 컨테이너의 /usr/test_hostvolume 디렉토리를 공유한다는 뜻입니다.

이때, 주의해야할 점!

1. 컨테이너의 디렉토리는 호스트의 디렉토리에 의해 덮어씌워집니다.
2. 호스트 또는 컨테이너에 해당 디렉토리가 없으면 새로 생성합니다.

 

제대로 공유가 되는지 컨테이너에서 파일을 생성해보고 호스트에서 공유가 되었는지 확인해볼게요!

[컨테이너에서 파일 생성]
docker exec web_hostvolume \
touch /usr/test_hostvolume/test.txt

[호스트에서 공유 확인]
$ cd ~/test-hostvolume
$ ls
test.txt

파일이 정상적으로 공유되었군요.

 

이 상태로 컨테이너를 삭제해볼까요?

docker stop web_hostvolume
docker rm web_hostvolume

 

다시 한 번 디렉토리를 확인해보면 데이터가 그대로 남아있는 것을 볼 수 있어요!

$ cd ~/test_hostvolume
$ ls
test.txt

 

-v 옵션으로 컨테이너와 호스트의 볼륨을 공유한 것을 그림으로 표현했어요.

컨테이너와 호스트 간의 디렉토리를 공유하는 것이 아닌 완전히 같은 디렉토리입니다.

 

 

Volume Container

-v 옵션으로 볼륨을 공유하던 컨테이너를 다른 컨테이너와 공유하는 방법이에요.

--volumes-from [Container-ID/Name] 옵션을 통해 사용이 가능해요.

 

첫 번째 공유했던 컨테이너처럼 똑같이 생성합니다. 이 친구가 중간자 역할을 해주는군요.

docker run -d \
--name web_hostvolume \
-p 80:80
-v ~/test_hostvolume:/usr/test_hostvolume \
httpd

 

그리고 Volume Container로써 공유받는 컨테이너를 생성합니다.

[컨테이너 생성]
docker run -it \
--name web_volumecontainer \
--volumes-from web_hostvolume \
ubuntu:16.04

[파일 공유 확인]
root@2d613e84e9b9:/# cd /usr/test_containervolume/
root@2d613e84e9b9:/usr/test_containervolume# ls
test.txt

 

이런 구조를 그림으로 나타내면 아래와 같겠군요!

그림처럼 여러 컨테이너가 동일한 컨테이너에 --volumes-from 옵션을 사용함으로써 볼륨을 공유해 사용할 수 있어요.

즉, 볼륨을 사용하려는 컨테이너에 -v 옵션 대신 --volumes-from 옵션으로 데이터를 간접적으로 공유받는 방식이에요.

이 구조를 이용하면 볼륨만 공유하는 '볼륨 컨테이너'역할을 수행할 수 있답니다.

 

 

Docker Volume

docker volume 명령을 사용할 수 있어요.

지금까지의 방법은 호스트와 볼륨을 공유해 컨테이너의 데이터를 보존했어요. 하지만 도커 자체에서 제공하는 볼륨 기능을 이용해 데이터를 보존할 수도 있습니다.

 

아래 명령어를 입력해 testvolume을 생성해주세요.

$ docker volume create --name testvolume
testvolume

 

docker volume ls 명령어로 생성한 볼륨을 확인합니다.

$ docker volume ls
DRIVER              VOLUME NAME
local               testvolume

볼륨을 생성할 때 플러그인 드라이버를 설정해 여러 종류의 스토리지 백엔드를 쓸 수 있지만 우리는 기본적으로 제공되는 드라이버인 local을 사용할거에요. 이 볼륨은 로컬 호스트에 저장되며 도커 엔진에 의해 생성되고 삭제됩니다!

 

생성한 볼륨을 사용하는 컨테이너를 만들어볼까요?

-v 옵션을 이용해 만들지만 [Volume Name]:[Container Directory] 형식으로 입력해줘야 한답니다.

docker run -it \
--name testvolume_1 \
-v testvolume:/root/ \
ubuntu:16.04

root@c7eb2f1d040e:/# echo hello, volume! >> /root/volume

/root 디렉토리에 volume이라는 파일을 생성했어요.

 

우리는 이제 예상할 수 있습니다. 다른 컨테이너도 해당 볼륨을 사용하면 volume이라는 파일이 있겠구나!

자, 두번째 컨테이너를 생성해봅시다.

docker run -it \
--name testvolume_2 \
-v testvolume:/root/ \
ubuntu:16.04

root@2409b6d0d916:~# cat /root/volume
hello, volume!

완벽해요! 같은 파일인 volume이 존재하는군요.

 

이 구조를 그림으로 표현하면 아래와 같아요.

볼륨은 디렉터리 하나에 상응하는 단위로서 도커 엔진에서 직접 관리하죠.

 

도커 볼륨도 호스트 볼륨 공유와 마찬가지로 호스트에 저장하긴 합니다!

사실 그냥 이용하는 입장에선 알 필요가 없겠지만 분명 궁금한 분이 계실거에요. 저도 그랬고요 ㅎㅎ

 

docker inspect 명령어를 사용하면 해당 볼륨이 어디에 저장되는지 알 수 있답니다.

$ docker inspect --type volume testvolume
[
    {
        "CreatedAt": "2020-07-16T12:21:21Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/testvolume/_data",
        "Name": "testvolume",
        "Options": {},
        "Scope": "local"
    }
]

Driver : 볼륨의 드라이버

Label : 볼륨을 구분하는 라벨

Mountpoint : 실제로 어디에 저장이 되었는지

 

반대로 컨테이너가 어떤 볼륨을 사용하는지 알고 싶다면 아래와 같이 입력해주시면 됩니다.

$ docker inspect --type container testvolume_2

.....
"Mounts": [
            {
                "Type": "volume",
                "Name": "testvolume",
                "Source": "/mnt/sda1/var/lib/docker/volumes/testvolume/_data",
.....

 

inspect 명령은 컨테이너, 이미지, 볼륨 등 도커의 모든 구성 단위의 정보를 확인할 때 사용하죠.
(정보의 종류를 확인할 때는 --type 옵션으로 입력합니다)

 

사실 Docker volume을 생성할 때에는 docker volume create 명령을 별도로 입력하지 않아도 컨테이너 생성 시 만들어지도록 설정 할 수 있어요.

아래와 같이 컨테이너에서 공유할 디렉터리 위치를 -v 옵션에 입력하면 해당 디렉터리에 대한 볼륨을 자동으로 생성합니다!

docker run -it \
--name volume_auto \
-v /root \
ubuntu:16.04

 

그리고, 도커 볼륨을 사용하다보면 불필요한 볼륨이 남아있을 때가 있어요. 볼륨을 사용하는 컨테이너를 삭제해도 볼륨은 자동으로 삭제가 되지 않기 때문인데요.

아래 명령어를 입력하면 한번에 삭제할 수 있어요.

docker volume prune
또는
docker volume rm $(docker volume list -q)

 


위에 내용들처럼 컨테이너가 아닌 외부에 데이터를 저장하고 컨테이너는 그 데이터로 동작하도록 설계하는 것을 무상태(Stateless)하다고 말합니다. 컨테이너 자체는 상태가 없고 상태를 결정하는 데이터는 외부로부터 제공받죠. 도커를 사용할 때 Stateless하도록 설계하는 것은 아주 바람직합니다. (Stateless 반대는 Stateful)

 

지금까지 Docker Container 를 효율적으로 관리하기 위한 볼륨 사용법을 알아봤어요. 끊임없이 효율을 추구하는 컨테이너 세상에서 우리가 배워나갈게 아주 많습니다.

긴 글 읽어주셔서 감사하고, 더욱 유익한 포스팅을 하도록 노력할게요!

 

 

 

'Simple is IT > Cloud & Container' 카테고리의 다른 글

Docker Container Logging_syslog(2/4)  (0) 2020.07.18
Docker Container Logging_logs(1/4)  (0) 2020.07.18
S3 WEB Hosting  (0) 2020.07.09
AWS S3는 무엇일까?  (0) 2020.07.09
K8S(kubernetes) 공식 문서  (0) 2020.06.06
Comments