Programming-[Infra]/Docker

도커 교과서(엘튼 스톤맨, 심효섭) - 5. volume, bind mount

컴퓨터 탐험가 찰리 2023. 3. 16. 08:23
728x90
반응형

1. 기록 가능 레이어와 이미지 레이어

 

 

하나의 이미지로 여러 개의 컨테이너를 생성하면, 각 컨테이너는 이미지의 레이어들을 기반으로 구성된다. 이 이미지 레이어들은 읽기 전용이다. 그리고 기록 가능 레이어(Writeable Layer)가 생성되어 각 컨테이너마다 다른 내용을 기록하고 저장할 수 있는 레이어가 생성된다.

 

컨테이너는 각자의 기록 가능 레이어를 갖는다

1. 같은 이미지로 이름만 변경해서 두 개의 컨테이너를 생성해본다.

docker container run --name rn1 diamol/ch06-random-number
docker container run --name rn2 diamol/ch06-random-number

 

2. docker cp 명령어를 사용하여 컨테이너에 있는 컨테이너 생성 시 무작위로 숫자를 쓴 파일을 로컬 컴퓨터로 복사해본다.

docker container cp rn1:/random/number.txt number1.txt
docker container cp rn2:/random/number.txt number2.txt

 

같은 이미지로 구성한 컨테이너라도 완전히 독립적으로 생성된다는 것을 확인할 수 있다. 다시 말해 기록 가능 레이어가 다르게 구성된 것이다.

 

 

기록 중 복사(copy-on-write)

이미지 레이어는 읽기 전용이지만 이미지 레이어에 포함된 파일을 기록 가능 레이어로 복사해와서 수정할 수 있다!

docker container run --name f1 diamol/ch06-file-display
echo "http://eltonstoneman.com" > url.txt
docker container cp url.txt f1:/input.txt
docker container start --attach f1

 

echo ... > 명령어는 파일을 생성하면서 ... 내용을 입력하라는 명령이다.

docker container start --attach {컨테이너 이름} 명령어는 컨테이너를 실행하되, 컨테이너의 출력 내용을 terminal 콘솔에 출력하라는 내용이다. 꼭 출력 뿐만 아니라 STDIN, STDOUT, STDERR 등을 보여줄 수 있다고 한다. 아래 참조

https://docs.docker.com/engine/reference/commandline/attach/

 

위 내용은 호스트 컴퓨터에 url.txt를 만들고 docker container cp 명령어로 f1 컨테이너의 input.txt에 붙여넣기를 한 후 도커를 재실행 하였을 때 내용이 바뀐다는 설명이다. 즉 원래 이미지 레이어에 있던 파일을 수정하였다. 이때 내부적으로는 해당 파일을 기록 가능 레이어로 가져가서 수정한다는 의미이다.

 

 

컨테이너의 파일 시스템은 일시적

컨테이너를 삭제하면 수정한 파일일지언정 컨테이너와 함께 삭제된다. 도커를 사용하다보면 컨테이너를 삭제하는 일이 잦으므로, 항상 컨테이너 자체의 파일 시스템은 일시적인 것이라고 생각해야한다. 컨테이너가 대체돼도 데이터를 유지하기 위한 파일 시스템이 도커 볼륨(volume)과 마운트(mount)이다.

 

 

 

 

2. 도커 볼륨(volume)

 

볼륨 생성, 확인

볼륨은 이미지, 컨테이너와 같은 레벨의 존재이다. 그래서 볼륨 관련 명령어도 docker volume ...으로 입력할 수 있다.교재에 나온 파일과 아래 명령을 통해 컨테이너와 연결된 볼륨을 갖는 컨테이너를 만들어본다. (터미널상에서 ch06/exercises/todo-list 디렉터리로 이동)

 

그리고 디렉터리상 Dockerfile에서 VOLUME 및 USER 명령어를 운영체제별로 주석문에 맞게 변경해준다.

 

 

# set in the base image - `/data` for Linux, `C:\data` for Windows
VOLUME /data

# set in the base image - `root` for Linux, `ContainerAdministrator` for Windows
USER root

 

 

이후 아래 명령어들을 실행한다.

docker container run --name todo1 -d -p 8010:80 diamol/ch06-todo-list
docker container inspect --format '{{.Mounts}}' todo1
docker volume ls

 

docker container inspect 명령으로 Mounts 항목을 확인해보면 볼륨의 ID, 볼륨이 연결된 파일 시스템 경로 등을 확인할 수 있다.

볼륨이 생성되는 것은 컨테이너 생성 시 VOLUME 명령어가 포함되어 있기 때문이다. 도커는 Dockerfile상 VOLUME 명령어가 있으면 볼륨을 생성한다. CLI 명령어상 volume 생성 명령어를 줘도 볼륨을 생성한다. 둘 다 있을 경우 CLI 명령어가 우선순위를 갖는다.

 

 

 

컨테이너간 볼륨 공유

 

docker container run -d --name t2 --volumes-from todo1 diamol/ch06-todo-list

(*예제 파일의 DockerFile에서 VOLUME $SQL_DATABASE 부분을 VOLUME /data로 수정함)

--volumes-from 플래그로 위에서 생성한 todo1 컨테이너와 새로 생성한 t2 컨테이너간 volume을 연결했다.

 

확인 방법1

아래 명령어를 통해 docker에 접속하여 각 컨테이너의 root/data에 접근해보면 똑같은 파일이 존재하는 것을 볼 수 있다.

 

docker exec -it {컨테이너 이름} sh

sh는 shell로 docker에 접속한다는 뜻이다. 이후 ls 명령어로 디렉터리를 확인해보면 data 디렉터리가 없지만. cd /data로 접속은 가능하다. 이것은 docker의 파일 시스템이 내가 명령을 실행하는 host 컴퓨터에서는 보이지 않기 때문이다. cd /를 통해 root로 이동해보면 /data가 존재하는 것은 볼 수 있다.

 

확인 방법2

volume의 id를 알아낸 뒤, 도커 데스크탑에서 UI로 확인할 수 있다. 아래 명령어를 입력한다.

docker container ps #여기서 실행 중인 컨테이너의 ID값 알아내기
docker container inspect {container ID} #여기서 Mounts 항목 중, Type: volume의 Name값

 

도커 데스크탑의 Volume 탭에서 해당 volume의 Name을 갖는 Volume에 접속해보면 아래와 같이 2개 컨테이너의 volume이 binding 되어있는 것을 확인할 수 있다.

 

 

* 컨테이너간 볼륨 공유는 파일 공유보다는 업데이트 간 상태를 보존하기 위한 용도로 사용해야한다.

특정 파일에 여러 컨테이너가 동시에 접근하면 각 컨테이너에서 실행하는 애플리케이션이 비정상적으로 동작할 수 있다.

 

* 볼륨을 직접 생성하고 컨테이너를 연결하여 컨테이너와 볼륨간 생애주기를 달리가져가는 것이 좋다.

target='/data' #복사 대상 경로를 환경 변수로 정의
docker volume create todo-list
docker container run -d -p 8011:80 -v todo-list:$target --name todo-v1 diamol/ch06-todo-list
#http://localhost:8011에 가서 데이터 추가
docker container rm -f todo-v1
docker container run -d -p 8011:80 -v todol-list:$target --name todo-v2 diamol/ch06-todo-list:v2

 

todo-v1 컨테이너가 삭제된 뒤에도 todo-v2에서도 volume에 추가되었던, volume에 의해 보존된 데이터를 확인할 수 있다.

 

 

 

3. 바인드 마운트

 

호스트의 파일 시스템(스토리지)을 컨테이너 파일 시스템의 디렉토리로 만드는 방식을 바인드 마운트라고 한다.

 

교재에서 제공하는 RAID 디스크 어레이가 있는 컨테이너와 로컬 컴퓨터의 /databases 디렉터리를 연결해본다.

source="$(pwd)/databases" && target='/data' #리눅스
mkdir ./databases
docker container run --mount type=bind,source=$source,target=$target -d -p 8012:80 diamol/ch06-todo-list
curl http://localhost:8012
ls ./databases

 

-참고 사항

--mount flag의 argument들을 입력할 때, comma 뒤에 띄어쓰기를 하면 안된다.

curl 명령어는 리눅스, macOS, 윈도우 모두에서 사용가능한 데이터 전송 툴이다. HTTP, FTP, SMTP 등 다양한 프로토콜을 지원한다.

 

 

바인드 마운트는 양방향으로 동작

바인드 마운트는 양방향으로 동작한다. 컨테이너에서 호스트 컴퓨터의 파일 수정이 가능하고 그 반대도 가능하다. 그렇기 때문에 호스트의 컴퓨터에 접근하기 위해서 Dockerfile 스크립트에서 USER 인스트럭션을 사용하여 권한을 부여한다(리눅스는 root, 윈도우는 ContainerAdministrator 계정)

 

#교재 todo-list 파일로 이동 후 입력
source="$(pwd)/config" && target='/app/config'
docker container run --name todo-configured -d -p 8013:80 --mount type=bind,source=$source,target=$target,readonly diamol/ch06-todo-list

curl http://localhost:8013 #작동 여부 확인
docker container logs todo-configured

 

readonly 설정을 추가하여 호스트 컴퓨터의 디렉토리에는 읽기 전용으로만 접근할 수 있도록 해주었다.

이 컨테이너의 애플리케이션은 /app/config 경로가 존재할 경우 여기서 추가 설정을 업로드하도록 되어있다. 컨테이너가 만들어지면서 호스트 컴퓨터의 config를 읽어와서 추가로 설정했기 때문에 logs 실행 시 많은 양의 로그가 보여진다.

 

한계점1. 바인드 마운트는 이미 존재하는 디렉터리를 대체

이미지 레이어 자체에서 어떤 디렉터리를 다루고 있는데, 바인드 마운트로 해당 디렉터리를 마운트해버리면 컨테이너에서의 디렉터리는 무시되고 컨테이너는 마운트된 새로운 디렉터리의 내용을 참조한다.

 

cd ./ch06/exercises/bind-mount
source="$(pwd)/new" && target='/init'
docker container run diamol/ch06-bind-mount
docker container run --mount type=bind,source=$source,target=$target diamol/ch06-bind-mount

 

이 이미지는 target 위치(/init)에 있는 디렉터리 목록을 출력한다. 첫 컨테이너는 컨테이너 자체의 디렉터리를 참조하여 abc.txt, def.txt를 출력하지만, 두 번째 컨테이너는 마운트된 디렉터리를 참조하여 123.txt, 456.txt를 출력한다

 

한계점2. 단일 파일 마운트는 파일이 중복 기록된다(리눅스만)

 

호스트 컴퓨터의 파일을 컨테이너에 이미 존재하는 디렉터리로 마운트하면 이미지에서 온 파일과 호스트에서 마운트된 파일이 모두 나타난다. 다만 이는 윈도 컨테이너에서는 작동하는 방식이 아니다. 마운트 명령어의 예시는 아래와 같다. 

 

docker container run --mount type=bind,source="$(pwd)/new/123.txt",target=/init/123.txt diamol/ch06-bind-mount

 

한계점3. 분산 파일 시스템(SMB, Azure Fileds, AWS S3 등)을 컨테이너에 마운트하면 에러가 발생할 수 있다.

SMB는 윈도우 파일 공유에 사용되는 분산 파일 시스템이다. 이런 시스템들은 컴퓨터 운영 체제의 파일 시스템과 다르게 구성된 경우가 많다. 따라서 이런 분산 파일 시스템을 컨테이너에 그대로 마운트하면 원하지 않는 동작이 발생할 수 있다.

 

728x90
반응형