도커 컨테이너의 파일 시스템과 데이터 관리
컨테이너 파일 시스템의 구조, 볼륨과 마운트를 통한 데이터 영속성 관리, 파일 시스템 베스트 프랙티스
도커 컨테이너의 파일 시스템과 데이터 관리
1. 컨테이너 파일 시스템
- 모든 컨테이너는 독립된 파일 시스템을 갖는다. 같은 이미지에서 실행한 여러 개의 컨테이너 중 한 컨테이너에서 애플리케이션이 파일을 수정해도 다른 컨테이너나 이미지는 영향을 받지 않는다.
- 컨테이너의 파일 시스템은 단일 디스크()다.
- 리눅스 컨테이너는 /dev/sda1, 윈도우 컨테이너는 C:\
- 이 디스크는 도커가 이미지 레이어와 컨테이너의 기록 가능 레이어로 부터 만들고 컨테이너에 전달한 가상 파일 시스템이다.
- 이미지 레이어는 모든 컨테이너가 공유하지만 기록 가능 레이어는 컨테이너마다 다르다.
- 이미지 레이어
- 읽기 전용
- 이미지를 내려받은 순간부터 삭제할 때까지 로컬 컴퓨터의 이미지 레이어에 존재
- 컨테이너의 기록 가능 레이어
- 컨테이너와 같은 생애주기를 가진다.
- 컨테이너를 실행할 때 생성되며 컨테이너를 삭제할 때 함께 삭제 (컨테이너 종료 시에는 데이터 그대로 남아 있다)
- 도커는 기록 중 복사(copy-on-write)라는 방법을 사용해 읽기 전용 레이어의 파일을 수정할 수 있다.
- 컨테이너에서 이미지 레이어에 포함된 파일을 수정하려 하면, 먼저 도커가 이 파일을 쓰기 가능 레이어로 복사해 온 다음 쓰기 가능 레이어에서 파일을 수정한다.
- 컨테이너 속 파일을 수정하면 컨테이너의 동작에 영향을 미친다. 그러나 이미지를 공유하는 다른 컨테이너나 이미지는 영향을 받지 않는다. 수정된 파일은 해당 컨테이너의 기록 가능 레이어에만 존재하기 때문이다.
- 컨테이너 파일 시스템은 컨테이너와 같은 생애주기를 갖는다. 컨테이너가 삭제되면 이 컨테이너의 기록 가능 레이어와 여기서 수정된 데이터도 함께 삭제된다.
- 실무에서는 새 이미지를 빌드하고 오래된 컨테이너를 삭제한 다음 새 이미지에서 실행한 컨테이너로 대체하는 방법으로 애플리케이션을 업데이트한다.
- 이 과정에서 기존 컨테이너에 있는 수정된 데이터는 모두 손실된다. 새 컨테이너는 이미지에서 받은 파일만 갖고 있기 때문이다.
- 도커 볼륨(Docker volume)과 마운트(mount)는 컨테이너와는 별개의 생애주기를 갖는다. 그래서 컨테이너가 대체돼도 지속돼야 할 데이터를 저장할 수 있다.
2. 도커 볼륨을 사용하는 컨테이너 실행
- 볼륨 마운트는 도커가 관리하는 객체인 볼룸과 컨테이너의 대상 디렉터리를 연결한다.
- 도커 볼륨은 도커에서 스토리지를 다루는 단위다.
- 볼륨은 컨테이너와 독립적으로 존재하며 별도의 생애주기를 갖지만, 컨테이너에 연결할 수 있다.
- 퍼시스턴시가 필요한 유상태 애플리케이션을 컨테이너로 실행하려면 볼륨을 사용해야 한다.
- 볼륨을 생성해 애플리케이션 컨테이너에 연결하면 나중에 애플리케이션을 업데이트하더라도 새로운 컨테이너에 다시 볼륨을 연결하면 데이터가 그대로 유지된다.
- 컨테이너에서 볼륨을 사용하는 방법
- 수동으로 직접 볼륨을 생성해 컨테이너에 연결하는 방법
- Dockerfile 스크립트에서 VOLUME 인스트럭션을 사용하는 방법 VOLUME
형식의 인스트럭션을 사용해 이미지를 만들고 컨테이너를 실행하면 자동으로 볼륨을 생성한다.
- 컨테이너 간 볼륨 공유
1
docker container run -d --name t3 --volumes-from todo1 diamol/ch06-todo-list
- 볼륨은 컨테이너 간 파일 공유보다는 컨테이너 업데이트 간 상태를 보존하기 위한 용도로 사용하는 것이 좋다.
- 볼륨은 이미지에서 정의하는 것보다는 명시적으로 관리하는 편이 더 낫다. 볼륨에 이름을 붙여 생성하고 업데이트 시 다른 컨테이너로 옮겨 연결하면 된다.
- 볼륨 생성
1
docker volume create todo-list
- 새 컨테이너 실행 시 컨테이너의 파일 시스템 경로에 지정한 볼륨을 마운트
1
docker container run -d -p 8011:80 -v todo-list:/data --name todo-v1 diamol/ch06-todo-list
- Dockerfile 스크립트의 VOLUME 인스트럭션과 docker container 명령의 –volume 플래그는 별개 기능이다.
- VOLUME 인스트럭션을 사용해 빌드된 이미지로 docker container run 명령에서 볼륨을 지정하지 않으면 항상 새로운 볼륨을 함께 생성한다. 이 볼륨은 무작위로 만들어진 식별자를 가지므로, 컨테이너를 삭제한 후 볼륨을 재사용하려면 이 식별자를 미리 기억해야 한다.
- 반면 –volume 플래그는 이미지에 볼륨이 정의돼 있든 말든 지정된 볼륨을 컨테이너에 마운트한다. 이미지에 볼륨이 정의돼 있더라도 이 정의가 무시되므로 새로운 볼륨이 생성되지 않는다.
- 이미지에 볼륨이 정의돼 있지 않아도 똑같은 결과를 얻는다. 이미지를 만드는 입장에서는 안전장치 삼아 VOLUME 인스트럭션을 이미지 정의에 포함시켜 두는 것이 좋다. 그러면 사용자가 볼륨을 지정하지 않더라도 데이터를 유실할 일이 없다. 하지만 사용자 관점에서는 이미지의 기본 볼륨 설정에 의존하지 않고 별도로 이름을 붙여 만든 볼륨을 사용하는 것이 좋다.
3. 파일 시스템 마운트를 사용하는 컨테이너 실행
- 바인드 마운트(bind mount)의 경우 호스트의 스토리지를 컨테이너에 좀 더 직접적으로 연결할 수 있는 수단이다.
- 바인드 마운트는 호스트 컴퓨터 스토리지의 특정 경로를 컨테이너의 대상 디렉터리로 연결한다. 원본 스토리지는 호스트 컴퓨터에서 접근 가능한 로컬 디스크와 네트워크 스토리지 모두 가능하다.
- 바인드 마운트는 양방향으로 동작한다. 컨테이너에서 만든 파일을 호스트 컴퓨터에서도 수정할 수도 있고, 반대로 호스트에서 만든 파일도 컨테이너에서 수정할 수 있다.
- 호스트 컴퓨터에 대한 공격을 방지하기 위해 컨테이너는 대개 최소 권한을 가진 계정으로 실행되는데, 바인드 마운트를 사용하면 호스트 컴퓨터 파일에 접근하기 위한 권한 상승이 필요하다. 그래서 Dockerfile 스크립트에서 USER 인스트럭션을 사용해 컨테이너에 관리자 권한을 부여한다.
- 파일에 쓰기 작업을 할 필요가 없다면 호스트 컴퓨터의 디렉터리를 읽기 전용으로 컨테이너에 연결할 수도 있다.
- 바인드 마운트를 적용해 컨테이너 실행
1
docker container run --name todo-configured -d -p 8013:80 --mount type=bind,source=$source,target=$target,readonly diamol/ch06-todo-list
- 호스트 컴퓨터가 접근할 수 있는 스토리지라면 무엇이든 바인드 마운트를 통해 컨테이너에 연결할 수 있다. 예를 들어 네트워크 드라이브가 경로 /mnt/nfs(리눅스)나 X: 드라이브(윈도우)에 연결돼 있다면 이 네트워크 드리아브를 바인드 마운트로 컨테이너에 연결할 수 있다.
4. 파일 시스템 마운트의 한계
- 이미 존재하는 대상 디렉터리에 마운트하면 마운트의 원본 디렉터리가 기존 디렉터리를 완전히 대체한다. 그래서 이미지에 포함돼 있던 원래 파일은 사용할 수 없다.
- 호스트 컴퓨터의 파일 하나를 컨테이너에 이미 존재하는 디렉터리로 마운트하면 디렉터리의 파일이 합쳐져 이미지에서 온 파일과 호스트에서 마운트된 파일이 모두 나타난다. 단, 윈도우 컨테이너는 이 기능을 제공하지 않아 동작이 달라진다.
- 컨테이너 파일 시스템은 윈도우 컨테이너와 리눅스 컨테이너의 동작이 일치하지 않는 몇 안 되는 영역 중 하나다.
- 동일하게 동작하는 경우는 Dockerfile 스크립트 내 경로 문자열이 그렇다. Dockerfile 스크립트에서 리눅스 스타일의 경로 문자열 \data를 사용해도 윈도우 컨테이너에서 그대로 C:\data의 별명으로 처리된다.
- 그러나 볼륨이나 바인드 마운트에서는 동작이 달라진다.
- 단일 파일 마운트는 리눅스 컨테이너와 윈도우 컨테이너에서 서로 다르게 동작한다.
- 리눅스 컨테이너에서는 단일 파일 마운트 기능을 사용할 수 있다. 대상 디렉터리가 컨테이너에 이미 존재한다면 마운트되는 디렉터리의 내용이 합쳐진다.
- 윈도우 컨테이너는 단일 파일 마운트 기능을 지원하지 않는다. 따라서 단일 파일 마운트를 사용하려 하면 ‘invalid mount config’ 에러 메시지가 출력되며 마운트 대상이 디렉터리여야 한다고 알려 준다.
- 분산 파일 시스템을 사용하면 네트워크상의 모든 컴퓨터에서 데이터에 접근할 수 있지만, 대개 분산 파일 시스템의 메커니즘은 윈도우 파일 공유에 쓰이는 SMB, Azure Files, AWS S3 등 로컬 컴퓨터 운영체제의 파일 시스템과 다른 경우가 많다. 이러한 분산 파일 스토리지를 컨테이너에 마운트하면 일반적인 파일 시스템의 일부터럼 보이기는 하겠지만 지원하지 않는 동작이 있을 수 있다.
- 예를 들어 Azure Files 서비스의 스토리지를 컨테이너 스토리지로 사용해 Postgres 데이터베이스를 실행한 경우, Azure Files는 읽기 및 쓰기 기능은 똑같이 제공하지만 지원하지 않는 기능이 있다. Azure Files가 지원하지 않는 기능인 파일 링크 생성을 시도하다 실패하는 경우 애플리케이션이 오류를 일으킨다.
- 이렇게 바인드 마운트의 원본 스토리지가 컨테이너에서 사용하는 모든 파일 시스템 기능을 제공하지 않을 수 있다. 그러나 이 사실은 애플리케이션을 실행해 보지 않고는 미리 파악할 방법이 없다.
- 컨테이너에 분산 스토리지를 마운트할 계획이라면, 이런 위험과 함께 분산 스토리지의 성능이 로컬 스토리지와 큰 차이가 있다는 것도 고려해야 한다.
- 디스크를 많이 사용하는 애플리케이션을 분산 스토리지를 마운트한 컨테이너에서 실행한다면 모든 파일 입출력이 네트워크를 거쳐야 하는 만큼 최악의 경우 애플리케이션이 멈춰 버릴 가능성도 있다.
5. 컨테이너 파일 시스템을 다루는 베스트 프렉티스
- 유니언 파일 시스템(Union File System)
- 모든 컨테이너는 도커가 다양한 출처로부터 모아 만든 단일 가상 디스크로 구성된 파일 시스템을 가지는데, 이를 유니언 파일 시스템이라 한다.
- 유니언 파일 시스템은 운영체제마다 다른 방식으로 구현돼 있다.
- 컨테이너는 유니언 파일 시스템을 통해 물리적 위치가 서로 다른 파일과 디렉터리에 마치 단일 디스크를 사용하듯 접근할 수 있다.
- 컨테이너에서 실행되는 애플리케이션의 입장에서는 단일 디스크만을 볼 수 있지만, 컨테이너나 이미지를 생성해 사용하는 사용자는 여러 출처를 합쳐 이 디스크를 구성할 수 있다.
- 기록 가능 레이어
- 비용이 비싼 계산이나 네트워크를 통해 저장해야 하는 데이터의 캐싱 등 단기 저장에 적합
- 각 컨테이너마다 독립적인 기록 가능 레이어를 갖지만, 컨테이너가 삭제되면 여기 저장된 데이터는 유실된다.
- 여러 개의 이미지 레이어 역시 하나 이상의 볼륨 마운트와 바인드 마운트를 컨테이너에 연결할 수 잇다. 그러나 기록 가능 레이어는 하나밖에 가질 수 없다.
- 로컬 바인드 마운트
- 호스트 컴퓨터와 컨테이너 간 데이터를 공유하기 위해 사용한다.
- 개발자의 로컬 컴퓨터에서 컨테이너로 소스 코드를 전달하기 위해 사용하면 로컬 컴퓨터에서 수정한 내용이 이미지 빌드 없이도 즉시 컨테이너로 전달될 수 있다.
- 분산 바인드 마운트
- 네트워크 스토리지와 컨테이너 간에 데이터를 공유하기 위해 사용한다. 가용성이 높지만 로컬 디스크와 비교해 지원하지 않는 파일 시스템 기능이 있거나 성능 면에서 차이가 있을 수 있다.
- 읽기 전용으로 설정 파일을 전달하거나 공유 캐시로 활용할 수 있으며 읽기 쓰기 가능으로 데이터를 저장해 동일 네트워크상의 모든 컨테이너나 컴퓨터와 데이터를 공유하는 데 적합하다.
- 볼륨 마운트
- 컨테이너와 도커 객체인 볼륨 간에 데이터를 공유하기 위해 사용된다.
- 볼륨 마운트를 사용하면 애플리케이션이 불륨에 데이터를 영구적으로 저장한다.
- 컨테이너를 교체하는 방식으로 애플리케이션을 업데이트 해도, 이전 버전 컨테이너의 데이터를 그대로 유지할 수 있다.
- 이미지 레이어
- 이미지 레이어는 컨테이너의 초기 파일 시스템을 구성한다.
- 레이어는 적층 구조를 갖는데, 후속 레이어와 이전 레이어의 내용이 서로 충돌하는 경우 후속 레이어의 내용이 적용된다. 레이어는 읽기 전용이며 여러 컨테이너가 공유한다.
- 컨테이너의 초기 상태는 이미지 레이어에서 받은 상태로만 구성된다. Dockerfile 스크립트에서 이미지로 복사한 모든 파일이 여기에 해당된다. 이들 레이어는 읽기 전용이지만 기록 중 복사 기법을 사용해 컨테이너에서 이들 파일을 수정할 수 있다.
This post is licensed under CC BY 4.0 by the author.