TechY
[개발 정리] Docker 튜토리얼 및 정리 2편 본문
첫 번째 정리에 이어서 두 번째 정리로 도커가 데이터를 관리하는 방법에 대해서 정리해보려 한다. 참고한 소스는 도커 공식 홈페이지의 docs를 보고 정리하였다.
기본적으로, 도커는 데이터를 writable layer 에 저장하기 때문에, container가 사라지면, 그 안에 있는 데이터도 함께 없어진다. 따라서, container 에서 저장한 데이터를 도커 호스트에 가져오기 위해서는, 마운트 옵션을 사용해야 하며, 이에 대한 유형은 아래와 같다.
- volume
- bind mount
- tmpfs mount
1. Volume
권장되는 마운트 유형으로, 위의 그림에서 보는 것과 같이, 호스트 파일 시스템에 도커 볼륨을 위한 경로가 따로 존재한다. 리눅스의 경우에는 "/var/lib/docker/volumes/" 이다. 왜 해당 유형이 가장 권장되는 것인지 살펴보자.
- 미리 정해진 도커만의 파일 시스템으로 Docker CLI 또는 API 로 관리가 가능하다.
- 유저가 정한 mount path 는 (bind-mount의 경우) file system 구조에 따라 가변적일 수 있어 배포 시 관리가 필요할 수 있지만, volume의 경우 그 경로가 완전히 도커에 의해 관리된다.
- bind-mount 보다 성능이 좋다.
이제 한번 볼륨 유형에 대한 커맨드를 살펴보자. 도커에 의해 관리되는 파일 시스템을 지원하는 만큼, 몇가지 cli 옵션이 있음을 알 수 있다.
1.1 Create Volume
docker CLI 로 my-vol이라는 볼륨을 생성하고, inspect 로 세부 사항을 보면, 위에서 언급한 경로에 볼륨 마운트 포인트가 생긴 것을 볼 수 있다.
docker volume create my-vol
1.2 Build Image
MLflow 를 위한 Dockerfile 을 하나 준비한다.
FROM continuumio/miniconda3
# Create the environment using conda
RUN conda install -c anaconda jupyter=1.0.0
RUN conda install -c conda-forge mlflow=1.20.2
RUN conda install -c conda-forge scikit-learn
RUN conda install -c anaconda psycopg2=2.8.5
RUN conda install -c anaconda boto3=1.14.12
# Set up SSH
RUN apt-get update && apt-get install -y openssh-server
RUN useradd -m -s /bin/bash dockeruser
RUN mkdir /var/run/sshd
RUN echo 'dockeruser:123' | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
그 후 이미지를 빌드하고, 컨테이너를 볼륨 마운트와 함께 실행해준다.
docker image build -t mlflow_image . # build image
docker run -d --name volumetest \
--mount type=volume,source=my-vol,target=/home/dockeruser mlflow_image
# run container with volume mounting
docker inspect volumetest # to check Mounts
마운트 유형이 볼륨으로 잘 생성된 것을 컨테이너 inspect 로 확인할 수 있다.
1.2 Copy the External data into Docker Volume
위와 같이 볼륨 마운트를 하고 컨테이너 실행을 끝낸 후에, 외부에서 컨테이너로 옮기고 싶은 파일이 생겼을 경우에, 어떻게 할까? bind-mount 의 경우, 어떠한 파일 시스템이든지 mount를 하기 때문에, 접근하여 파일을 해당 경로로 옮기면 되지만, docker volume의 경우에는 이렇게 할 경우 몇 가지 문제가 생긴다고 한다. 결국 docker volume에는 물리적인 접근을 지양하는 것이 좋다는 것이다. 몇 가지 해결 방법이 있는데, bind-mount 를 사용하는 것도 있지만, 우선 docker volume 을 사용한다는 전제에서 권장되는 방법은 docker api 를 사용하는 것이다. 순서는 아래와 같다.
- 데이터를 전송하려는 docker volume 을 mount 한 temporal container를 만든다. (volume만 있을 경우)
- docker cp 명령어로 로컬에서 마운트된 볼륨의 경로로 데이터를 copy & paste
- 1을 했을 경우, container 를 삭제한다.
1.2.1 docker cp
리눅스 명령어 cp 와 사용방법이 거의 동일하다. 첫 번째 인자에는 복사하려는 파일 경로 두 번째 인자에는 복사하여 둘 경로이다. 한국말이 어려우니 아래 명령어를 보면 더욱 간단하다.
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH # from container to local machine
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH # from local machine to container
그렇게 해서 나온 커맨드는 아래와 같다.
docker container create --name temp -v my-vol:/data hello-world
docker cp data.csv temp:/data
docker rm temp
2. Bind-Mount
bind mount 유형도 docker volume과 크게 다르지 않다. 다만, volume create 명령어가 따로 있는 것이 아닌, host file system 의 경로를 명시해주면서 마운트가 진행된다.
docker run -d \
--mount type=bind,source=$(pwd),target=/home/dockeruser \
--name mlflow_container mlflow_image
container가 local directory 에 bind-mount 된 경로의 데이터를 쓰지 않고 읽게만 하려고 한다면 readonly 옵션을 주면 된다.
docker run -d \
--mount type=bind,source=$(pwd),target=/home/dockeruser,readonly \
--name mlflow_container mlflow_image
2.1 Mount into a non-empty directory on the container
비어있지 않은 디렉터리에 bind-mount 를 할 경우, 컨테이너를 실행하면서 오류가 발생하게 된다. 예로 들면, nginx container 의 /usr directory에는 이미 파일이 있는 non-empty 상태인데, 이때 bind-mount 를 실행하려고 할 경우, runtime error 가 발생한다.
docker run -d \
-it \
--name broken-container \
--mount type=bind,source=/tmp,target=/usr \
nginx:latest docker: Error response from daemon: oci runtime error:
container_linux.go:262: starting container process caused "exec: \"nginx\":
executable file not found in $
3.tmpfs
이름에서 알려준데로 임시 파일 시스템 역할을 하는 마운트 유형으로, docker host 의 파일 시스템에 마운트가 되는 것이 아닌, 메모리에 임시적으로 공유된다. 민감한 파일을 다룰 때, 사용된다고 한다.
docker run -d \
-it \
--name tmptest \
--mount type=tmpfs,destination=/app \
nginx:latest
Conclusion
docker 에서 데이터를 관리하는 방법들에 대해서 크게 3가지를 간략하게 알아보았다. 간단한 실험을 할 경우에, local machine 에 있는 데이터를 간단하게 마운트하면서, 실습을 해두면 더 많이 배울 수 있지 않을까 싶다. 다음 포스팅에는 docker network 에 대해 다루도록 하겠다.
'[개발 정리] > [Docker]' 카테고리의 다른 글
[개발 정리] Docker 튜토리얼 및 정리 3편 (0) | 2021.09.12 |
---|---|
[개발 정리] Docker 튜토리얼 및 정리 1편 (0) | 2021.09.09 |