← all posts
DEV 2026.05.02 · 16 min read Intermediate

Docker 스토리지는 어디서 끝나고 어디서 시작되는가

컨테이너의 일시성과 데이터의 영속성이 충돌하는 지점부터 볼륨 드라이버, 스토리지 드라이버, 백업 전략까지 — Docker 스토리지 설계의 통일된 원칙을 추적한다.


Docker를 처음 쓰는 팀이 가장 먼저 당하는 사고는 데이터베이스 컨테이너를 삭제했을 때 데이터가 사라지는 것이다. 볼륨을 붙이면 해결되는 것 같지만, 그다음엔 Named Volume과 Anonymous Volume의 차이가 뭔지, Bind Mount와 Tmpfs는 언제 써야 하는지, Storage Driver는 Volume Driver와 어떻게 다른지 혼란이 쌓인다. 이 모든 혼란에는 하나의 공통 원인이 있다 — Docker가 “레이어”와 “마운트”를 구분하지 않은 채 스토리지를 이야기하기 때문이다. 이 두 개념을 먼저 가르는 것이 나머지 모든 것을 이해하는 열쇠다.

두 개의 스토리지 세계

Docker 스토리지는 목적이 완전히 다른 두 세계로 나뉜다.

Storage Driver는 이미지 레이어와 컨테이너 레이어를 관리한다. docker pull로 받은 이미지는 읽기 전용 레이어의 스택이고, 컨테이너를 실행하면 그 위에 쓰기 가능한 얇은 레이어가 하나 얹힌다. 이 레이어 시스템 전체를 관장하는 것이 Storage Driver다. Linux 기본값인 overlay2는 OverlayFS를 사용해 상위 레이어(Upper)와 하위 레이어(Lower)를 단 두 개로 합친다. 읽기는 하위 레이어를 직접 참조하고, 쓰기가 발생하면 해당 파일을 상위 레이어로 복사한 뒤 수정한다 — 이것이 Copy-on-Write다.

Volume Driver는 컨테이너 외부의 영속 스토리지를 관리한다. 컨테이너가 삭제되어도 데이터가 살아남아야 하는 곳이다.

Container Layer (R/W)  ← Storage Driver 영역
Image Layer 3  (R/O)
Image Layer 2  (R/O)
Image Layer 1  (R/O)
────────────────────────
Named Volume            ← Volume Driver 영역
/var/lib/docker/volumes/my-vol/_data

이 구분을 모르면 “왜 컨테이너에 쓴 파일이 사라지지?”와 “왜 볼륨에 쓴 파일은 남아있지?”를 같은 질문으로 착각하게 된다. 앞은 Storage Driver 문제, 뒤는 Volume Driver 문제다.

볼륨 타입의 선택: Named, Bind, Tmpfs

세 가지 마운트 타입은 각각 다른 문제를 해결한다.

Named Volume은 Docker가 관리하는 영속 저장소다. /var/lib/docker/volumes/<name>/_data에 저장되며, 컨테이너가 삭제되어도 볼륨은 남는다. 데이터베이스, 사용자 업로드, 애플리케이션 상태 — 프로덕션 데이터의 기본 선택이다.

Bind Mount는 호스트의 특정 경로를 컨테이너 내부에 직접 연결한다. 변경이 양방향으로 즉시 반영되기 때문에 개발 환경의 Hot Reload에 최적이다. 단, 호스트 경로에 의존하므로 이식성이 낮고 프로덕션에서는 설정 파일(읽기 전용)이나 로그 수집 이외의 용도로 쓰는 것은 피한다.

Tmpfs Mount는 RAM을 파일시스템처럼 사용한다. 컨테이너가 재시작되면 내용이 사라지지만, 속도는 디스크 대비 10~50배 빠르다.

# 성능 비교 (1GB 쓰기)
# Named Volume (SSD): ~1.2초
# Tmpfs (메모리):     ~0.3초
Anonymous Volume의 함정

-v /app/data처럼 이름 없이 선언된 볼륨은 해시값 이름으로 자동 생성된다. 컨테이너 삭제 후에도 볼륨이 남아 디스크를 잠식한다. docker volume prune으로 정리하기 전까지는 고아 볼륨으로 쌓인다. DockerfileVOLUME 지시어도 같은 방식으로 Anonymous Volume을 만든다. 대부분의 경우 Named Volume을 명시적으로 선언하는 것이 옳다.

Storage Driver: overlay2가 기본인 이유

Storage Driver는 사용자가 바꿀 일이 거의 없다. 하지만 동작을 모르면 성능 문제가 어디서 오는지 파악할 수 없다.

overlay2가 기본인 이유는 단순하다. 커널 3.18 이상이면 별도 설치 없이 동작하고, inode를 효율적으로 공유하며, page cache를 레이어 간에 공유해 메모리 효율도 높다. 10개의 컨테이너가 같은 nginx 이미지를 쓸 때 기반 레이어는 단 한 벌만 메모리에 올라간다.

대안이 필요한 경우는 명확하다. 엔터프라이즈 환경에서 비트 부패(bit rot) 방지와 스냅샷 백업이 필요하면 ZFS, 대용량 ML 이미지를 압축해 저장해야 한다면 btrfs. devicemapper는 Docker 18.09부터 deprecated됐다 — 쓰지 않는다.

# 현재 Storage Driver 확인
docker info | grep "Storage Driver"
# Storage Driver: overlay2

Volume Driver: 로컬을 넘어서

단일 호스트에서는 local 드라이버로 충분하다. 그런데 컨테이너가 다른 호스트로 마이그레이션되거나 여러 노드에서 같은 데이터를 공유해야 할 때, 로컬 드라이버는 한계에 부딪힌다.

NFS는 가장 단순한 해결책이다. --opt type=nfs로 볼륨을 만들면 원격 NFS 서버의 경로가 컨테이너에 마운트된다. 여러 컨테이너가 동시에 같은 볼륨을 읽는 워크로드(정적 파일, 로그 수집)에 적합하다. 단, 여러 컨테이너가 동시에 쓰는 경우엔 파일 잠금 메커니즘이 없으면 데이터가 깨진다.

복제와 고가용성이 필요하면 GlusterFS(파일 기반 복제)나 Ceph(블록/오브젝트/파일 통합)로 이동한다. 클라우드 환경이라면 REX-Ray를 통해 AWS EBS, Azure Disk, GCP Persistent Disk를 Docker 볼륨으로 쓸 수 있다.

데이터 영속성: 백업과 마이그레이션

Named Volume이 있어도 스토리지 장애나 실수로 docker volume rm을 치면 데이터는 사라진다. 영속성은 볼륨만으로 완성되지 않는다 — 백업이 있어야 한다.

가장 간단한 백업 패턴은 임시 컨테이너로 볼륨을 tar로 압축하는 것이다.

docker run --rm \
  -v postgres-data:/source:ro \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/backup-$(date +%Y%m%d).tar.gz -C /source .

데이터베이스는 이보다 한 단계 위인 pg_dump 같은 논리 백업이 낫다. 파일 레벨 백업은 데이터베이스가 쓰는 중이면 일관성이 깨질 수 있기 때문이다. 복원은 반드시 정기적으로 테스트한다 — 백업 파일이 있어도 복원이 안 되면 소용없다.

버전 업그레이드나 다른 데이터베이스로의 마이그레이션에서 블루-그린 패턴이 유용하다. 기존 인스턴스(Blue)를 유지한 채 새 인스턴스(Green)를 준비하고 데이터를 동기화한 뒤 스위치한다. 문제가 생기면 Blue로 즉시 롤백할 수 있다.

트레이드오프

스토리지 선택의 트레이드오프

Named Volume vs Bind Mount: Named Volume은 Docker가 관리하므로 이식성이 높고 초기 컨테이너 내용을 볼륨으로 복사해준다. Bind Mount는 호스트 경로를 직접 노출하므로 개발 편의성은 높지만, Mac/Windows에서는 가상화 레이어를 거쳐 성능이 크게 떨어진다.

overlay2 vs ZFS: overlay2는 설정이 단순하고 성능이 뛰어나지만 스냅샷과 체크섬이 없다. ZFS는 비트 부패 방지와 네이티브 스냅샷을 제공하지만 커널 모듈 설치가 필요하고 운영 복잡도가 높다.

Tmpfs: 속도가 필요한 캐시와 임시 파일에는 탁월하지만, 재시작 시 데이터가 사라진다. 메모리 크기를 초과하면 스왑에 쓰이므로 --memory-swap으로 스왑을 막지 않으면 보안에 민감한 데이터에 위험할 수 있다.

정리

  • Storage Driver(overlay2)는 이미지/컨테이너 레이어를 관리하고, Volume Driver는 영속 데이터를 관리한다 — 이 둘을 혼동하면 디버깅이 꼬인다.
  • Named Volume이 프로덕션 기본값이다. Anonymous Volume은 고아 볼륨을 만들고, Bind Mount는 호스트 경로에 종속된다.
  • Tmpfs는 캐시와 임시 파일에 쓰고, NFS/Ceph/GlusterFS는 멀티호스트 공유나 고가용성이 필요할 때 선택한다.
  • 볼륨이 있어도 백업 없이는 영속성이 보장되지 않는다. 자동화된 백업과 정기적인 복원 테스트가 세트다.

Docker 스토리지의 복잡함은 선택지가 많아서가 아니라, 각 선택지가 어떤 문제를 풀기 위해 설계됐는지를 모를 때 온다. 레이어와 마운트, Storage Driver와 Volume Driver — 이 경계선을 명확히 하면 나머지는 따라온다.