컨테이너의 스토리지(볼륨)에 대해서 알아보고, 실습해보도록 하겠습니다.
도커 이미지로 컨테이너를 생성하면, 그 이미지는 읽기 전용으로 사용 가능합니다.
운영중인 컨테이너에 데이터를 저장해도, 컨테이너가 종료되면 모두 사라지게 되는거죠.
이런 컨테이너의 특성때문에, 영구적으로 사용할 수 있는 스토리지를 마운트 하여 사용할 수있도록 합니다. :)
Docker의 영구 스토리지(볼륨) 는 도커볼륨, 호스트, 볼륨컨테이너 이렇게 3가지로 구분됩니다.
각 실습을 통해 자세히 보도록 하겠습니다.
1. Docker Storage - Docker Volume
도커 볼륨은 도커 자체에서 제공하는 볼륨 기능입니다.
1-1) Docker Volume 생성 및 할당
먼저 Docker Volume을 먼저 테스트 해보겠습니다.
docker volume create 명령어로 볼륨을 생성합니다.
[root@docker /]# docker volume create docker-volume
docker-volume
컨테이너를 실행하면서, -v 옵션으로 도커 볼륨을 마운트합니다.
-v <도커볼륨>:<컨테이너내부 마운트 디렉토리>
[root@docker /]# docker run --name nginx -d -v docker-volume:/usr/share/nginx/html -p 8080:80 nginx
c875a4d6b242a88ebb217b93961dcfee584d073412cd7c71757944ff2094536d
컨테이너 잘 실행되었는지 확인합니다.
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c875a4d6b242 nginx "/docker-entrypoint.…" 54 seconds ago Up 53 seconds 0.0.0.0:8080->80/tcp nginx
실행중인 컨테이너에 접속하여, index.html 파일을 수정합니다.
[root@docker /]# docker container exec -it nginx /bin/bash
root@c875a4d6b242:/# echo 'Docker-volume test' > /usr/share/nginx/html/index.html
root@c875a4d6b242:/# cat /usr/share/nginx/html/index.html
Docker-volume test
root@c875a4d6b242:/# exit
exit
도커 볼륨 경로(/var/lib/docker/volume/docker-volume/)의 index.html이 도커 컨테이너 내부에서 변경한 내용인지 확인합니다.
[root@docker /]# cat /var/lib/docker/volumes/docker-volume/_data/index.html
Docker-volume test
1-2) Docker Volume 공유하여 사용
컨테이너를 하나 더 생성할건데, 이 컨테이너는 위에서 생성한 컨테이너와 마찬가지로 docker-volume 을 마운트하여 사용합니다.
자, 먼저 같은 도커볼륨(docker-volume)을 공유하는 컨테이너를 생성합니다.
[root@docker /]# docker run --name nginx2 -d -v docker-volume:/usr/share/nginx/html -p 8081:80 nginx
dd2e2aa330f3de4eb974e330f4d1117b5703ece14018620cb721af8d6abe4d66
컨테이너 목록을 확인합니다. :)
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd2e2aa330f3 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:8081->80/tcp nginx2
c875a4d6b242 nginx "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:8080->80/tcp nginx
두개의 컨테이너는 동일한 도커 볼륨을 마운트하고 있으므로, 같은 결과를 반환할것 입니다.
두개의 컨테이너의 http 응답을 확인해봅니다 :)
[root@docker /]# curl 127.0.0.1:8080/index.html
Docker-volume test
[root@docker /]# curl 127.0.0.1:8081/index.html
Docker-volume test
1-3) 컨테이너 삭제 후 Docker Volume 볼륨 확인
위에서 설명한것처럼 컨테이너에서 저장되는 데이터는 컨테이너가 종료될때 같이 사라지는, 일종의 휘발성 데이터였습니다.
이런 컨테이너의 특성을 보완하기 위해 영구 스토리지를 마운트 할 수 있고, 그중 하나가 Docker volume 이었습니다.
그러면, 이제 컨테이너를 삭제하고 컨테이너에서 작성했던 index.html의 내용이 잘 남아있는지 확인해보도록 하겠니다. :)
자, 먼저 컨테이너 목록을 확인합니다.
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd2e2aa330f3 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:8081->80/tcp nginx2
c875a4d6b242 nginx "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 0.0.0.0:8080->80/tcp nginx
nginx 컨테이너를 삭제하고, 목록을 한번 더 확인해봅니다.
[root@docker /]# docker container rm -f nginx
nginx
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd2e2aa330f3 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:8081->80/tcp nginx2
방금 삭제한 nginx 컨테이너와 같은 볼륨을 마운트하고 있던 nginx 컨테이너에 index.html을 요청해보겠습니다.
동일한 응답을 하네요 :)
[root@docker /]# curl 127.0.0.1:8081/index.html
Docker-volume test
이번에는 nginx2 컨테이너까지 삭제 하겠습니다.
[root@docker /]# docker container rm -f nginx2
nginx2
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
볼륨 목록을 확인합니다.
[root@docker /]# docker volume ls
DRIVER VOLUME NAME
local 8237040d29f8abe25ea512695e510d7a856cd944f1807638e64e0c9e69f43548
local docker-volume
실 저장경로에서 데이터를 확인합니다 .
두 컨테이너를 모두 삭제했지만, 도커 볼륨에는 데이터가 그대로 남아있네요 :)
[root@docker /]# ls /var/lib/docker/volumes/docker-volume/_data/
50x.html index.html
[root@docker /]# cat /var/lib/docker/volumes/docker-volume/_data/index.html
Docker-volume test
1-4) 도커 볼륨 삭제
도커 볼륨을 확인합니다.
[root@docker /]# docker volume ls
DRIVER VOLUME NAME
local 8237040d29f8abe25ea512695e510d7a856cd944f1807638e64e0c9e69f43548
local docker-volume
docker volume prune 명령어로 도커 볼륨을 모두 삭제합니다.
[root@docker /]# 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
Deleted Volumes:
8237040d29f8abe25ea512695e510d7a856cd944f1807638e64e0c9e69f43548
docker-volume
Total reclaimed space: 124.4MB
도커 볼륨 목록을 확인합니다. 모두 지워졌네요.
[root@docker /]# docker volume ls
DRIVER VOLUME NAME
위에서 확인했던, 도커 볼륨 경로를 확인합니다.
삭제되었기떄문에 경로를 찾을수 없네요 :)
[root@docker /]# ls /var/lib/docker/volumes/docker-volume/_data/
ls: cannot access /var/lib/docker/volumes/docker-volume/_data/: 그런 파일이나 디렉터리가 없습니다
2. Docker Storage - Host Volume
호스트 볼륨은 도커 컨테이너가 호스트의 특정 볼륨을 마운트하여 사용하는 옵션 입니다.
2-1) Host Volume 생성 및 할당
호스트 컴퓨터에 web_data 라는 디렉터리를 생성하겠습니다.
[root@docker /]# mkdir /web_data
/web_data 경로를 마운트하여 컨테이너를 실행합니다 ( -v 옵션 )
[root@docker /]# docker run --name nginx1 -v /web_data:/usr/share/nginx/html -d -p 8881:80 nginx
0dc2dd87ba1b9a88161dc521fb60d3e7d8587cc969e1dd623fe948df16cde00f
컨테이너 접속 후 테스트 파일을 생성합니다. "This is host volume test" 라는 hostvolume.html 파일이 생성되었습니다.
이 테스트 파일이 저장되는 경로는 호스트 볼륨에 마운트 되어있으므로, 컨테이너 내부에서 수정된 파일 내용을 호스트에서도 확인할 수 있게 됩니다. :)
[root@docker /]# docker exec -it nginx1 /bin/bash
root@0dc2dd87ba1b:/# echo 'This is host volume test' > /usr/share/nginx/html/hostvolume.html
root@0dc2dd87ba1b:/# exit
exit
컨테이너에 http 요청에 대한 응답을 확인합니다.
hostvolume.html 파일이 잘 생성되었네요 :)
[root@docker /]# curl 127.0.0.1:8881/hostvolume.html
This is host volume test
컨테이너 내부에서 수정한 파일은 결국, 호스트에 특정 디렉터리에 저장되고 있습니다.
호스트의 /web_data 디렉터리를 살펴보면, hostvolume.html 파일이 존재하고, 컨테이너 내부에서 작성한 내용과 같음을 볼수있습니다.
[root@docker /]# ls -al /web_data/hostvolume.html
-rw-r--r--. 1 root root 25 9월 28 07:41 /web_data/hostvolume.html
[root@docker /]# cat /web_data/hostvolume.html
This is host volume test
2-2) Host Volume 공유하여 사용
컨테이너 목록을 확인합니다. 컨테이너 nginx가 실행중이네요!
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0dc2dd87ba1b nginx "/docker-entrypoint.…" 11 minutes ago Up 11 minutes 0.0.0.0:8881->80/tcp nginx1
nginx2 컨테이너를 새로 생성합니다.
[root@docker /]# docker run --name nginx2 -v /web_data:/usr/share/nginx/html -d -p 8882:80 nginx
de6703a65ce132837ac2485a871d81b674842a58d53c71aef3b1ced0bef98f83
컨테이너 목록을 확인해봅시다. 이제 2개의 컨테이너가 실행되고있습니다.
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
de6703a65ce1 nginx "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 0.0.0.0:8882->80/tcp nginx2
0dc2dd87ba1b nginx "/docker-entrypoint.…" 11 minutes ago Up 11 minutes 0.0.0.0:8881->80/tcp nginx1
두개의 컨테이너가 모두 잘 동작하고 있는지 확인해봅시다 :)
[root@docker /]# curl 127.0.0.1:8881/hostvolume.html
This is host volume test
[root@docker /]# curl 127.0.0.1:8882/hostvolume.html
This is host volume test
호스트 컴퓨터의 /web_data 경로의 hostvolume.html 파일을 확인해봅니다.
"This is host volume test"라고 적혀 있네요 :)
[root@docker /]# ls -al /web_data/
합계 4
drwxr-xr-x. 2 root root 29 9월 28 07:41 .
dr-xr-xr-x. 18 root root 259 9월 28 07:38 ..
-rw-r--r--. 1 root root 25 9월 28 07:41 hostvolume.html
[root@docker /]# cat /web_data/hostvolume.html
This is host volume test
자, 그럼 이제 호스트 컴퓨터 /web_data 경로에 새로운 파일을 추가해보고 컨테이너에서 어떻게 응답을 주는지 확인해보겠습니다.
/web_data/test.html 을 생성합니다.
[root@docker /]# echo 'This is additional File for host volume' > /web_data/test.html
두개의 컨테이너 모두 새로운 test.html요청에 대해 잘 응답 하네요 :)
[root@docker /]# curl 127.0.0.1:8881/test.html
This is additional File for host volume
[root@docker /]# curl 127.0.0.1:8882/test.html
This is additional File for host volume
2-3) 컨테이너 삭제 후 Host Volume 볼륨 확인
이번 단계에서는 컨테이너를 모두 삭제해보고 호스트 컴퓨터의 볼륨을 확인해보겠습니다.
컨테이너 목록을 확인합니다.
아직 두개의 컨테이너가 잘 동작하고 있네요!
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
de6703a65ce1 nginx "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:8882->80/tcp nginx2
0dc2dd87ba1b nginx "/docker-entrypoint.…" 17 minutes ago Up 17 minutes 0.0.0.0:8881->80/tcp nginx1
컨테이너를 전체 삭제합니다.
[root@docker /]# docker rm -f $(docker ps -aq)
de6703a65ce1
0dc2dd87ba1b
컨테이너 목록을 확인합니다. 전체 컨테이너가 모두 삭제되었습니다.
[root@docker /]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
이제 호스트 컴퓨터의 /web_data 경로를 확인해볼까요?
컨테이너가 모두 삭제되었음에도 이 경로에 데이터는 모두 남아있네요!
[root@docker /]# ls -al /web_data/
합계 8
drwxr-xr-x. 2 root root 46 9월 28 07:56 .
dr-xr-xr-x. 18 root root 259 9월 28 07:38 ..
-rw-r--r--. 1 root root 25 9월 28 07:41 hostvolume.html
-rw-r--r--. 1 root root 40 9월 28 07:56 test.html
3. Docker Storage - Container Volume
다른 컨테이너에서 사용하는 볼륨을 동일하게 마운트하여 사용합니다. (컨테이너에 설정된 볼륨을 똑같이 따라 쓴다고 보시면 될것같아요!)
이때 주의할점은 -v 옵션이 적용된 컨테이너의 볼륨 디렉터리를 공유할 수 있습니다.
자, -v <호스트 디렉토리 경로>:<컨테이너 디렉토리 경로> 옵션을 준 컨테이너를 실행해봅니다.
이 옵션으로 호스트 컴퓨터의 /web_data 디렉토리가 컨테이너의 /usr/share/nginx/html 디렉토리와 마운트 됩니다.
[root@docker /]# docker run --name nginx_v -v /web_data:/usr/share/nginx/html -d -p 8001:80 nginx
433d6937ccf0330d8d3284d08ff0dc29e52b60a9172dcb5bde8021b944e41f9d
자, 이 nginx_v 컨테이너가 잘 응답하는지 확인해봅시다. 잘 응답하네요 :)
[root@docker /]# curl 127.0.0.1:8001/test.html
This is additional File for host volume
이번에는 nginx_v의 볼륨을 사용하는 nginx1 컨테이너를 생성해봅니다.
[root@docker /]# docker run --name nginx1 --volumes-from nginx_v -d -p 8002:80 nginx
0ef8c76b9b59036c81baedec407ce504f350d1e5e2de2a11102d968790a64de6
이번에는 nginx1 컨테이너가 잘 응답하는지 확인해봅시다. 역시나 잘 응답하네요!
[root@docker /]# curl 127.0.0.1:8002/test.html
This is additional File for host volume
혹시나 해서 보니까, -v 옵션이 적용안된 컨테이너에는 마운트가 안되더라구요!
다시말해서, -v 옵션이 적용 된 컨테이너에만 컨테이너 볼륨을 사용할수 있습니다.
마지막으로, 테스트 해보겠습니다!
nginx1 컨테이너를 실행해봅시다. (이름이 바로 위 실습한 컨테이너랑 겹치는데 docker rm ngnix 명령어로 다 삭제해주세요!)
[root@docker /]# docker run --name nginx1 -d -p 8981:80 nginx
9fdf61286dc66b3404b0fdda6d346b59d696bbc4b551a7fb201df14a44e601ed
컨테이너에 접속해서 index.html 파일을 생성합니다.
[root@docker /]# docker exec -it nginx1 /bin/bash
root@9fdf61286dc6:/# echo 'test html for container volume' > /usr/share/nginx/html/index.html
root@9fdf61286dc6:/# exit
exit
자 이 컨테이너의 index.html 응답을 확인해봅니다.
[root@docker /]# curl 127.0.0.1:8981/index.html
test html for container volume
nginx1을 마운트하는 nginx2를 생성합니다.
[root@docker /]# docker run --name nginx2 --volumes-from nginx1 -d -p 8982:80 nginx
a28483b81d377648c363d5d107692593dca75ee2c373d106b0211b3128de95aa
스토리지를 공유하는지 확인하기 위해 http 응답을 확인합니다.
공유하지 않네요 :)
<!-- 스토리지를 공유하는지 확인하기위해 http 응답 확인 (공유하지 않음) -->
[root@docker /]# curl 127.0.0.1:8982/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
이번 볼륨 포스팅은 여기까지입니다 :)