[Infra] 도커(docker)(7) 도커 볼륨(docker volume)을 이용한 데이터 관리
업데이트:
도커(docker)(7) 도커 볼륨(docker volume)을 이용한 데이터 관리
참고링크
참고 링크
- (0)도커의 개념
- (1)도커 설치하기, hello world!
- (2)도커 컨테이너 조작 기초(pull, run, ps)
- (3)도커 이미지 변경 후 저장(commit)
- (4)도커 컨테이너 네트워크
- (5)도커 API 이미지 빌드 및 컨테이너 실행
- (6)도커 컴포즈를 활용한 여러 개의 Flask, Nginx 배포
- (7)도커 볼륨을 이용한 데이터 관리
- (8)도커 장고 이미지 살펴보기
- (9)도커 PostgreSQL 컨테이너 배포
- (1)쿠버네티스 구조
- (2)쿠버네티스 설치
- (3)쿠버네티스 서비스 배포하기
- (4)컨테이너 IP와 파드 IP의 관계
- (5)퍼시스턴트 볼륨 스토리지
- (6)쿠버네티스 에러 메시지
1. 컨테이너 내부에서 생성된 데이터를 보존하려면?
도커를 사용하면 컨테이너를 활용해 서비스 배포를 쉽게 할 수 있습니다. 그리고 서비스 중에는 컨테이너 내부에 여러가지 새로운 파일들이 생성될 수 있는데요. 웹 서비스라면 로그파일, 머신러닝이라면 모델 파일 등과 같은 데이터가 발생할 것입니다. 그런데 만약 컨테이너를 삭제한다면 새롭게 생겨난 데이터들은 어떻게 될까요? 이를 위해 도커 볼륨(docker volume)을 사용합니다.
2. 도커 볼륨
도커 볼륨은 호스트 서버에 존재하며 컨테이너 속 파일들과 연동시키기 위해 사용합니다. 도커 볼륨을 사용하지 않을 경우 컨테이너를 삭제하면 컨테이너 가동 후에 발생된 파일들이 모두 사라지게 됩니다. 따라서 도커 볼륨을 사용하면 컨테이너를 삭제하더라도 변경/추가된 파일들은 모두 유지됩니다.
nginx와 flask api 서버를 하나 띄워보겠습니다. 다음과 같은 docker-compose.yml 파일을 하나 작성합니다. 우리의 목적은 model_test 컨테이너에서 발생되는 데이터를 도커 볼륨을 통해 보존하는 것입니다.
version: "3"
services:
model_test:
build: ./model_test
volumes:
- test02-tensorflow-volume:/model_test
container_name: model-test02
restart: always
expose:
- "6001"
nginx:
build: ./nginx
container_name: nginx-test02
restart: always
ports:
- "9001:9001"
depends_on:
- model_test
volumes:
test02-tensorflow-volume:
가장 아래 파트에 있는 volumes: 는 도커 볼륨을 생성하겠다는 의미입니다. 볼륨의 이름은 test02-tensorflow-volume라고 짓겠습니다. 그리고 이렇게 생성된 도커 볼륨은 model_test 컨테이너와 연동 됩니다. model_test를 보시면 volumes: 라는 파트가 추가되었는데 이는 볼륨을 사용하겠다는 뜻입니다. 볼륨을 마운트 하는 방법은 그 다음 줄 처럼 source:destination 형식으로 쓰면 됩니다. source에 해당하는 것은 마운트 하고자 하는 볼륨 이름을 쓰면 되고 destination에 해당하는 것은 마운트 될 컨테이너의 디렉토리 명을 쓰면 됩니다. 위 문서를 보면 컨테이너 내부의 루트 경로 바로 아래의 /model_test 경로가 도커 볼륨과 연결되는 것을 알 수 있습니다. 경로를 아는 방법은 도커 파일을 보시면 알 수 있습니다.
model_test의 도커 파일은 다음과 같습니다.
FROM python:3.8.5
WORKDIR /model_test
COPY . .
RUN python -m pip install --upgrade pip
RUN pip install -r requirements.txt
# server
CMD gunicorn main:app --bind 0.0.0.0:6001 --timeout 3000
위 도커 파일을 보면 WORKDIR 경로가 컨테이너 상에서 루트 바로 아래인 /model_test라는 것을 알 수 있습니다.
따라서 이 상태로 서비스를 배포하면 됩니다.
$ docker compose -d --build
[+] Running 3/3
⠿ Network test02_default Created 0.0s
⠿ Container model-test02 Started 0.4s
⠿ Container nginx-test02 Started
그리고 잘 배포 되었는지 확인해 보겠습니다.
$ docker container ls | grep test
78bd97283373 test02_nginx "/docker-entrypoint.…" 5 seconds ago Up 3 seconds 80/tcp, 0.0.0.0:9001->9001/tcp, :::9001->9001/tcp nginx-test02
f922abec434d test02_model_test "/bin/sh -c 'gunicor…" 5 seconds ago Up 4 seconds 6001/tcp model-test02
model-test02 컨테이너를 이용해 딥러닝 모형을 학습시킵니다. 학습된 h5 파일은 컨테이너 내부에 떨어집니다. 그리고 이 파일들은 도커 볼륨으로 관리됩니다.
$ docker compose down
[+] Running 3/3
⠿ Container nginx-test02 Removed 0.4s
⠿ Container model-test02 Removed 10.3s
⠿ Network test02_default Removed
그리고나서 컨테이너를 삭제했다가 다시 살려보겠습니다.
$ docker compose up -d --build
[+] Running 3/3
⠿ Network test02_default Created 0.0s
⠿ Container model-test02 Started 0.4s
⠿ Container nginx-test02 Started
컨테이너를 다시 살리고 컨테이너 내부를 보면 아까 학습시켰던 모형이 그대로 있는 것을 볼 수 있습니다.
$ docker exec -it model-test02 /bin/bash
root@f922abec434d:/model_test# ls
Dockerfile __pycache__ data main.ipynb main.py model mymodel.ipynb mymodel.py requirements.txt
root@f922abec434d:/model_test# cd model/
root@f922abec434d:/model_test/model# ls
b5b2209af2129fda72a7272e802b5c90881ac303e768b0c05f368951200e0f4b.h5
c45f80dbb7e8dd328ef26bea989b34b5c449cb7124168e3f4faab2d52da38e85.h5
e89a7e33f7c1db0820cf74e5198b3d96c7218c327138e6d07aa7818bac2bd707.h5
볼륨에 대한 정보를 확인하고 싶다면 다음 커맨드를 입력합시다.
$ docker inspect test02_test02-tensorflow-volume
[
{
"CreatedAt": "2022-04-05T16:16:43+09:00",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "test02",
"com.docker.compose.version": "2.2.2",
"com.docker.compose.volume": "test02-tensorflow-volume"
},
"Mountpoint": "/var/lib/docker/volumes/test02_test02-tensorflow-volume/_data",
"Name": "test02_test02-tensorflow-volume",
"Options": null,
"Scope": "local"
}
]
위와 같이 정보를 확인하면 도커 볼륨이 저장되는 경로도 알 수 있습니다.
3. 위 방식대로 했을 때의 문제점
위 방식대로 했을 때 하나의 문제점이 있습니다.
앞서 만든 docker-compose.yml
파일을 다시 보면 다음과 같습니다.
version: "3"
services:
model_test:
build: ./model_test
volumes:
- test02-tensorflow-volume:/model_test
container_name: model-test02
restart: always
expose:
- "6001"
nginx:
build: ./nginx
container_name: nginx-test02
restart: always
ports:
- "9001:9001"
depends_on:
- model_test
volumes:
test02-tensorflow-volume:
위 파일을 보면 볼륨의 경로가 /model_test
라는 것을 알수 있는데요.
이 말은 /model_test
경로 아래의 모든 파일을 볼륨으로 보존한다는 의미입니다.
즉, 다음과 같은 파일을 보존합니다.
위 그림에서 빨간 박스 내의 영역이 도커 볼륨으로 보존되는 파일들입니다.
그런데 잘보면 main.py
파일이 보존되는 것을 볼 수 있는데,
이러면 추후에 로컬에서 main.py
파일을 수정한 다음 다시 컨테이너로 올리면 파일이 수정된 버전으로 바뀌지 않습니다.
이를 확인해보겠습니다.
먼저 컨테이너에 접속해 main.py
파일을 확인해보겠습니다.
$ docker exec -it model-test02 /bin/bash
root:/model_test# ls
Cockerfile data main.py model mymodel.py requirements.txt
root:/model_test# cat main.py
아래 그림 확인
위와 같이 파일을 확인하면 다음 그림과 같이 중간에 주석이 있는 것을 볼 수 있습니다.
컨테이너를 내리고 주석을 지운다음 다시 올려보겠습니다. 일단 컨테이너를 내리겠습니다.
$ docker compose down
[+] Running 3/3
⠿ Container nginx-test02 Removed
⠿ Container model-test02 Removed
⠿ Network test02_default Removed
로컬에서 해당 파일의 21번 줄을 다음과 같이 주석을 없애고 올려보겠습니다.
주석을 없앴습니다. 그럼 컨테이너를 다시 올려보겠습니다.
$ docker compose up -d --build
[+] Running 3/3
⠿ Network test02_default Created
⠿ Container model-test02 Started
⠿ Container nginx-test02 Started
그리고나서 다시 해당 컨테이너로 가서 파일을 확인해보면 주석이 안지워진것을 볼 수 있습니다.
그렇다면 주석을 지우려면 어떻게 해야할까요? 일단 컨테이너를 다시 내립시다.
$ docker compose down
[+] Running 3/3
⠿ Container nginx-test02 Removed
⠿ Container model-test02 Removed
⠿ Network test02_default Removed
위에서 우리가 보존하고 있는 파일들은 다음과 같다고 했습니다.
이렇게 했을때의 문제점은 main.py
가 보존되어 업데이트가 적용되지 않습니다.
이 문제를 해결하려면 다음과 같이 보존 영역을 바꾸어야 합니다.
이를 위해 docker-compose.yml
파일을 수정해주겠습니다.
version: "3"
services:
model_test:
build: ./model_test
#image: work_kpt_supply_chain
volumes:
- test02-tensorflow-volume:/model_test/model
container_name: model-test02
restart: always
expose:
- "6001"
nginx:
build: ./nginx
container_name: nginx-test02
restart: always
ports:
- "9001:9001"
depends_on:
- model_test
volumes:
test02-tensorflow-volume:
위 파일을 보면 볼륨 경로가 /model_test/model
로 바뀐것을 볼 수 있습니다.
이러고나서 다시 컨테이너를 올리고
$ docker compose up -d --build
[+] Running 3/3
⠿ Network test02_default Created
⠿ Container model-test02 Started
⠿ Container nginx-test02 Started
그리고 컨테이너 내부 파일을 확인하면
$ docker exec -it model-test02 /bin/bash
root:/model_test# ls
Cockerfile data main.py model mymodel.py requirements.txt
root:/model_test# cat main.py
아래 그림 확인
파일 수정이 적용된 것을 알 수 있습니다.