[GDSC] Docker 실전 환경 이해하기 | 파일, 볼륨, 그리고 데이터 유지
지난 글에서 이미지와 컨테이너, 그리고 레이어 구조를 통해 도커가 어떻게 “가볍고 재현 가능한 환경”을 만드는지 살펴봤다. 이미지는 여러 층의 읽기 전용 레이어로 구성되어 있고, 컨테이너는 그 이미지 위에 마지막 쓰기 레이어를 얹어 실행된다는 점도 확인했다.
이제 한 단계 더 들어가 보자.
“컨테이너 안에서 만든 파일은 어디에 저장될까?” “컨테이너가 지워지면 내 데이터는 어떻게 될까?”
처음 Docker를 접하면 대개 명령어와 실행 방식에 집중하느라 이런 부분을 놓치곤 하지만, 실제 서비스 운영 단계에 들어가면 이 질문이 매우 중요해진다. 왜냐하면, 데이터가 어떻게 저장되고 유지되는지 모르면, 로그가 사라지고, 환경설정이 초기화되고, 심지어 데이터베이스가 통째로 날아가는 경험을 하게 될 수 있기 때문이다.
🧩 컨테이너 안에 파일을 저장하면 무슨 일이 벌어질까?
컨테이너를 실행하면 Docker는 이미지 위에 쓰기 가능한 레이어(writable layer) 하나를 올린다. 우리가 컨테이너 안에서 파일을 생성하거나 변경하면, 이 레이어에 정보가 기록된다. 즉, 컨테이너 내부에 보이는 파일 시스템은 “이미지의 여러 읽기 전용 레이어 + 마지막 쓰기 레이어”가 합쳐진 모습이다.
겉으로 보기엔 완전한 하나의 파일 시스템처럼 보인다. 그래서 컨테이너 안에서 echo "Hello" > memo.txt라고 입력하면 파일이 잘 만들어진다. 당장 그 파일을 읽어보면 아무 문제 없어 보인다.
하지만 컨테이너를 삭제해보면… 파일도 함께 사라진다. 왜냐하면 그 파일은 오직 컨테이너의 쓰기 레이어에만 존재했고, 컨테이너와 함께 운명이 끝났기 때문이다.
즉, 컨테이너 내부는 임시 저장소이며, 컨테이너가 살아있는 동안만 유지되는 공간이다.
“왜 마음대로 파일을 못 남기지?”라고 생각할 수 있지만, 이게 바로 도커가 가진 장점이기도 하다. 컨테이너는 본질적으로 “재사용 가능한 프로그램 실행 단위”이며, 언제든 기존 것을 버리고 새로 띄울 수 있도록 설계되어 있기 때문이다.
이 설계는 개발과 배포를 자동화하는 데 매우 적합하다. 컨테이너는 동일한 이미지에서 항상 깨끗한 환경을 보장한다. 언제든 버리고 새로 만들 수 있는 것이다.
하지만 서비스 운영 관점에서는 이야기가 달라진다.
로그나 사용자 데이터, 데이터베이스 같은 정보는 사라지면 안 된다.
이때 필요한 것이 바로 볼륨(Volume)이다.
💾 Docker에서 다루는 3가지 데이터
컨테이너 안에 들어가는 모든 데이터가 같은 성질을 갖는 건 아니다. 목적과 “지속되기 원하는 정도”에 따라 다음 세 가지로 나눌 수 있다.
- 소스 코드 및 환경 데이터 (이미지에 포함되는 데이터)
우리가 작성한 코드, 의존성, 실행 환경 등은 이미지에 baked된다. 읽기 전용이고, 바꾸고 싶으면 이미지 자체를 다시 빌드해야 한다.
→ 앱 자체의 “정체성” 같은 데이터
- 일시적 데이터 (컨테이너 쓰기 레이어에 저장되는 데이터)
컨테이너 실행 중 생성되는 임시 파일들. 로그, 캐시, 임시 업로드 파일 같은 것들이다.
→ 컨테이너가 사라지면 함께 사라진다. → 없어져도 되는 데이터이거나, 다시 생성 가능한 데이터.
- 영구 데이터 (반드시 남아야 하는 데이터)
사용자 계정, DB 파일, 중요한 로그 등 컨테이너가 죽어도 살아남아야 하는 데이터들이다
📦 Docker Volume: 컨테이너 밖에 보관되는 데이터
볼륨은 쉽게 말하면, 컨테이너 밖에 위치한 지속되는 저장소다. 컨테이너 내부에 있는 것처럼 보이지만, 실제로는 Docker가 따로 관리하는 공간에 저장된다.
이 덕분에 컨테이너를 삭제해도 데이터가 유지된다. 심지어 동일한 볼륨을 여러 컨테이너가 공유할 수도 있다.
예를 들어 웹 애플리케이션과 로그 수집기를 따로 컨테이너로 운영하고 싶다고 하자. 두 컨테이너가 같은 로그 파일을 공유해야 하므로, 볼륨을 사용하면 깔끔하게 해결된다.
운영 환경에서는 볼륨을 통해 중요한 데이터를 보호하고 관리한다. 볼륨은 컨테이너의 라이프사이클과 분리되어 있기 때문에, 안정성과 일관성을 보장한다.
볼륨 방식에도 두 가지가 있다.
도커가 이름을 관리하는 Named Volume이 있고, 이름 없이 매핑만 되는 Anonymous Volume이 있다.
Named Volume은 컨테이너가 사라져도 계속 남아 있기 때문에 운영 환경에서 자주 사용된다.
반면 Anonymous Volume은 기본적으로 데이터가 컨테이너 바깥에 저장되는 볼륨이 맞긴 한데, 이름이 없기 때문에 나중에 어떤 컨테이너가 사용했는지 추적하거나 관리하기가 사실상 어렵다. 그래서 대부분의 경우 컨테이너와 함께 정리되며, 장기 보관 목적보다는 컨테이너 내부의 특정 디렉토리를 바인드 마운트로 덮어쓰지 않기 위한 보호 용도나 테스트·임시 환경처럼 “잠깐 쓰고 버리는” 상황에 적합하다.
🧲 바인드 마운트: 로컬 디렉토리를 그대로 연결하기
볼륨과 비슷하지만 역할이 조금 다른 방식이 있다.
바로 바인드 마운트(Bind Mount)다.
볼륨이 “Docker가 관리하는 데이터 저장 영역”이라면, 바인드 마운트는 내 로컬 컴퓨터의 특정 폴더를 직접 컨테이너에 연결하는 방식이다.
이 방식이 특히 유용한 순간이 있다: 바로 개발 환경에서 코드 수정이 즉시 반영되어야 할 때다.
로컬 IDE(VSCode 등)에서 파일을 수정하면, 컨테이너 안에서도 그 변화가 즉시 나타난다. 따라서 라이브 리로드(Hot reload) 기반의 개발 환경에서 매우 편리하다.
정리하면,
- 개발 단계에서는 바인드 마운트를 사용해 빠르게 수정하고 테스트한다.
- 운영 단계에서는 볼륨을 사용해 안전하게 데이터와 상태를 유지한다.
컨테이너는 가볍고 일시적인 실행 단위다. 이 철학은 바뀌지 않는다. 단지, 우리가 필요에 따라 “변하지 않아야 하는 데이터”를 밖에 두는 것뿐이다.