컨테이너는 기본적으로 휘발성이다. 컨테이너가 삭제되면 내부 파일도 함께 사라진다. 데이터베이스나 업로드 파일처럼 영구 보존이 필요한 데이터는 Volume을 통해 컨테이너 외부에 저장해야 한다. Docker Compose는 이를 선언적으로 관리할 수 있는 깔끔한 방법을 제공한다.
두 가지 방식은 데이터를 어디에, 어떻게 저장하느냐에서 차이가 난다.
| 구분 | Named Volume | Bind Mount |
|---|---|---|
| 저장 위치 | Docker가 관리하는 내부 경로 | 호스트의 특정 디렉터리 |
| 선언 방식 | 최상위 volumes: 블록 필요 | 호스트 경로를 직접 지정 |
| 이식성 | 높음 | 낮음 (경로 의존) |
| 주요 용도 | DB 데이터, 캐시 | 소스 코드, 설정 파일 |
Named Volume: Docker Engine이 직접 생성·관리하는 볼륨. docker volume ls로 확인 가능.
Bind Mount: 호스트 파일시스템의 경로를 컨테이너 내부에 직접 연결하는 방식.
Named Volume을 사용하려면 compose.yml 최상위에 volumes: 블록을 먼저 선언해야 한다. 이 선언이 없으면 Compose는 해당 볼륨을 인식하지 못한다.
volumes:
postgres_data:
redis_cache:
이렇게 선언된 볼륨은 docker volume ls에서 <project>_postgres_data 형태로 확인할 수 있다.
[Host / Docker Volume] [Container]
───────────────────── ─────────────────────
postgres_data (Named Volume) ── /var/lib/postgresql/data
./nginx/conf.d (Bind Mount) ── /etc/nginx/conf.d (ro)
./app/src (Bind Mount) ── /app/src
각 서비스는 volumes: 키에서 위 볼륨을 마운트한다.
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
volumes:
- postgres_data:/var/lib/postgresql/data
cache:
image: redis:7
volumes:
- redis_cache:/data
web:
image: nginx:alpine
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
volumes:
postgres_data:
redis_cache:
마운트 경로 끝의 :ro는 read-only 옵션이다. 컨테이너가 해당 경로에 쓰기를 시도하면 오류가 발생한다.
PostgreSQL은 데이터 파일을 /var/lib/postgresql/data에 저장한다. Named Volume 없이 컨테이너를 재시작하면 모든 데이터가 초기화된다.
# 볼륨 목록 확인
docker volume ls
# 볼륨 상세 정보 (실제 저장 경로 포함)
docker volume inspect myproject_postgres_data
# 볼륨을 유지하며 컨테이너만 재생성
docker compose up -d --force-recreate db
docker compose down은 컨테이너와 네트워크를 삭제하지만 볼륨은 유지한다. 볼륨까지 삭제하려면 --volumes 플래그를 명시해야 한다.
# 컨테이너 + 볼륨 모두 삭제 (데이터 영구 삭제 주의)
docker compose down --volumes
이미 존재하는 볼륨을 Compose가 새로 생성하지 않고 그대로 사용하게 하려면 external: true를 지정한다.
volumes:
shared_data:
external: true
external: true로 선언된 볼륨이 존재하지 않으면 docker compose up 시 오류가 발생한다. 사전에 docker volume create shared_data로 생성해두어야 한다.
Named Volume은 데이터 영속성과 이식성을 동시에 확보하는 가장 안전한 방법이다. Bind Mount는 개발 중 소스 코드 실시간 반영처럼 호스트와 긴밀하게 연동해야 할 때만 선택적으로 사용한다.