Docker 볼륨 기초: 데이터를 컨테이너 밖에서 관리하기
컨테이너가 삭제되면 데이터도 사라지는 문제를 Docker 볼륨으로 해결하는 방법을 기초부터 정리합니다. 볼륨 생성·마운트·삭제 명령어와 -v, --mount 차이를 다룹니다.
지난 글에서 Dockerfile 안티 패턴을 살펴봤다. 이번 글부터는 볼륨(Volume) 섹션으로 넘어간다. 컨테이너는 기본적으로 에페메럴(ephemeral)하다. 컨테이너를 삭제하면 그 안에 쌓인 데이터도 함께 사라진다. 데이터베이스 파일, 업로드된 이미지, 로그 같이 컨테이너 생명 주기와 무관하게 보존해야 하는 데이터를 다루려면 볼륨이 필요하다.
문제: 컨테이너 레이어는 임시다
Docker 이미지는 읽기 전용 레이어로 구성된다. 컨테이너를 실행하면 그 위에 얇은 쓰기 가능 레이어가 추가된다. 컨테이너 안에서 파일을 생성하거나 변경하면 이 레이어에 기록된다. 문제는 docker rm으로 컨테이너를 지우면 이 쓰기 레이어도 함께 삭제된다는 점이다.
# 컨테이너 안에서 파일 생성
docker run --name test-container ubuntu bash -c "echo 'hello' > /data/test.txt"
# 컨테이너 삭제
docker rm test-container
# 다시 실행해도 test.txt는 없다
docker run --name test-container ubuntu ls /data/
# ls: cannot access '/data/': No such file or directory
볼륨이란
볼륨은 Docker가 관리하는 호스트 파일시스템 내의 특정 디렉터리다. 컨테이너와 독립적으로 존재하므로 컨테이너가 삭제되어도 볼륨은 남는다. 여러 컨테이너가 같은 볼륨을 동시에 마운트할 수도 있다.
- 컨테이너 생명주기와 분리된 독립적인 데이터 저장소
- Docker 데몬이
/var/lib/docker/volumes/경로에서 관리 (Linux 기준) - Windows·Mac에서는 Docker Desktop 내부 VM이 해당 경로를 관리
볼륨 기본 명령어
# 볼륨 생성
docker volume create my-data
# 볼륨 목록 확인
docker volume ls
# DRIVER VOLUME NAME
# local my-data
# 볼륨 상세 정보
docker volume inspect my-data
# [
# {
# "Name": "my-data",
# "Driver": "local",
# "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
# ...
# }
# ]
# 볼륨 삭제
docker volume rm my-data
# 사용 중이 아닌 볼륨 일괄 삭제
docker volume prune
볼륨을 컨테이너에 마운트하기
볼륨을 컨테이너에 연결하는 방법은 두 가지다.
-v 플래그 (단축 문법)
docker run -d \
-v my-data:/app/data \
--name web \
nginx
형식은 볼륨이름:컨테이너경로다. 볼륨이 없으면 자동으로 생성된다.
--mount 플래그 (명시적 문법)
docker run -d \
--mount type=volume,source=my-data,target=/app/data \
--name web \
nginx
--mount는 키=값 형식으로 파라미터를 명시해 의도가 명확하다. 특히 여러 사람이 작업하는 프로젝트나 스크립트에서 가독성이 높다.
볼륨 데이터 확인
마운트한 볼륨에 실제로 데이터가 저장되는지 확인해보자.
# 볼륨을 마운트해서 컨테이너 실행
docker run --name writer \
-v my-data:/app/data \
ubuntu \
bash -c "echo 'persistent data' > /app/data/test.txt"
# 컨테이너 삭제
docker rm writer
# 새 컨테이너에서 같은 볼륨을 마운트하면 데이터가 살아있다
docker run --rm \
-v my-data:/app/data \
ubuntu \
cat /app/data/test.txt
# persistent data
컨테이너가 삭제된 뒤에도 볼륨에 기록한 파일은 그대로 남아있다.
볼륨 vs 이미지 내장 데이터
볼륨을 마운트하는 경로에 이미지 안에 파일이 있으면 어떻게 될까?
# nginx 이미지는 /usr/share/nginx/html에 기본 HTML이 있다
docker run -d -v my-data:/usr/share/nginx/html nginx
- 볼륨이 비어있으면: 이미지의 기존 파일이 볼륨으로 복사된다 (초기화)
- 볼륨에 이미 데이터가 있으면: 볼륨 내용이 이미지 내용보다 우선한다
이 동작은 named volume에서만 적용된다. bind mount는 호스트 디렉터리를 그대로 덮어씌운다.
실습: PostgreSQL 데이터 보존
볼륨의 실제 사용 예시로 PostgreSQL을 들어보자.
# 볼륨 생성
docker volume create pgdata
# PostgreSQL 컨테이너 실행
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# DB에 데이터 추가 후 컨테이너 삭제 및 재시작해도 데이터 유지
docker stop postgres && docker rm postgres
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# 이전 데이터가 그대로 남아있다
핵심 정리
- 컨테이너 쓰기 레이어는 컨테이너와 함께 삭제된다 → 볼륨으로 해결
docker volume create→docker run -v또는--mount로 마운트- 볼륨은 컨테이너 삭제 후에도 독립적으로 존재
- 비어있는 볼륨에는 이미지의 기존 파일이 초기화됨
- 프로덕션에서 DB·파일 업로드·설정 등 중요 데이터는 반드시 볼륨 사용
다음 글: Docker 볼륨 종류: Named, Anonymous, Bind Mount, tmpfs 비교
읽어주셔서 감사합니다. 😊