Postgres 볼륨 경로가 3년 틀렸는데 멀쩡했던 이유 — VOLUME 선언이 몰래 붙인 이름 없는 볼륨
데이터는 경로가 아니라 볼륨 이름을 따라간다. down 을 쓰는 사람만 DB 를 잃는다
docker-compose 의 Postgres 볼륨이 db:/data/db 로 잡혀 있었다. MongoDB 경로다. 3년 전 처음 세팅할 때 내가 넣은 실수였다. 그런데 나는 그동안 DB 가 날아간 적이 한 번도 없었고, 동료는 「컨테이너를 다시 띄울 때마다 DB 가 사라진다」 고 했다.
결론부터. 경로가 틀려도 Postgres 는 잘 돈다. 이미지가 VOLUME 으로 선언한 경로에 Docker 가 이름 없는 볼륨을 붙여 주기 때문이다. 그 볼륨은 down 하는 순간 버려진다. 지금 쓰는 compose 파일의 DB 볼륨 줄을 한 번 확인해 볼 만하다.
무엇이 붙어 있었나
db:
image: postgres:16
volumes: ["db:/data/db"] # Postgres 는 여기를 안 쓴다
공식 postgres 16 이미지의 Dockerfile 에는 이 두 줄이 있다.
ENV PGDATA /var/lib/postgresql/data
VOLUME /var/lib/postgresql/data
VOLUME 은 「이 경로는 컨테이너 밖에 둔다」 는 선언이다. compose 가 그 경로에 아무것도 안 붙이면 Docker 가 이름 없는(anonymous) 볼륨을 하나 만들어 붙인다. 실제 모습은 이랬다.
이름 있는 볼륨 db 는 아무도 안 쓰는 /data/db 에 붙어 3년 동안 비어 있었다. 진짜 데이터는 해시 이름이 붙은 이름 없는 볼륨에 있었다.
왜 나만 멀쩡했나 — 습관이 갈랐다
| 명령 | 고치기 전 (이름 없는 볼륨) | 고친 뒤 (이름 있는 볼륨) |
|---|---|---|
stop · start · restart |
남음 | 남음 |
up -d 로 컨테이너 재생성 |
남음 | 남음 |
down → up |
빈 DB | 남음 |
rm 뒤 up, up -V |
빈 DB | 남음 |
down -v, volume prune |
빈 DB | 빈 DB |
up 으로 컨테이너를 새로 만들 때 compose 는 이전 컨테이너의 이름 없는 볼륨을 넘겨받는다. 공식 문서의 -V, --renew-anon-volumes 설명이 「이전 컨테이너에서 데이터를 가져오는 대신 이름 없는 볼륨을 다시 만든다」 이니, 기본은 넘겨받기다. 나는 up 과 stop 만 썼고 동료는 down 으로 정리하는 습관이 있었다. 버그는 하나인데 증상은 사람마다 달랐다.
처음에 헷갈렸던 것
「경로가 같으면 데이터도 남아야 하지 않나」 라고 생각했다. 아니었다. 컨테이너를 새로 만들면 파일 시스템도 이미지에서 새로 펼쳐진다. 데이터가 남는 건 그 경로에 같은 이름의 볼륨이 다시 붙을 때뿐이다. 데이터는 경로가 아니라 볼륨 이름을 따라간다.
/var/lib/postgresql/data 는 Mac 의 경로도 아니다. 컨테이너 안 경로이고, 실제 파일은 Docker Desktop VM 안 /var/lib/docker/volumes/<프로젝트명>_db/_data 에 있다. Homebrew 로 깐 Postgres 와도 섞이지 않는다.
내 Mac 에는 어디에도 안 붙은 볼륨(docker volume ls -qf dangling=true)이 32개 있었다. 몇 개가 지난 down 때 버려진 DB 인지는 아직 세어 보지 않았다.
다른 DB 의 줄을 복사해 오면 똑같이 터진다
공식 이미지의 VOLUME 은 제각각이다 (각 Dockerfile · Docker Hub 설명, 2026-10-19 확인).
| 이미지 | VOLUME |
|---|---|
| postgres 17 이하 | /var/lib/postgresql/data |
| postgres 18 이상 | /var/lib/postgresql (PGDATA 는 /var/lib/postgresql/18/docker) |
| mysql | /var/lib/mysql |
| mongo | /data/db, /data/configdb |
| redis | /data |
다른 프로젝트 compose 에서 볼륨 줄만 가져오면 이번 같은 일이 난다. Postgres 18 로 올릴 때도 같은 자리를 다시 본다. Docker Hub 설명은 18 부터 마운트를 /var/lib/postgresql 로 하라고 적고 있다. 17 시절의 :/var/lib/postgresql/data 줄을 그대로 두면 PGDATA 가 그 밖에 놓인다.
확인하는 법
docker image inspect postgres:16 --format '{{json .Config.Volumes}}'
docker inspect $(docker compose ps -q db) --format '{{json .Mounts}}'
두 번째 결과에서 PGDATA 경로에 붙은 볼륨의 Name 이 64자 해시라면 이 함정이다.
볼륨 세 가지, 언제 무엇을
| 종류 | 이럴 때 |
|---|---|
이름 있는 볼륨 (db:/var/lib/postgresql/data) |
로컬 개발 DB 의 기본. down 해도 남는다 |
bind mount (./tmp/pg:/var/lib/postgresql/data) |
데이터를 폴더째 보거나 들고 다니고 싶을 때 |
| 이름 없는 볼륨 | 버려도 되는 캐시. DB 에는 쓰지 않는다 |
로컬 개발 환경이 사람마다 다르게 깨진다면, 대개 이런 숨은 기본값 하나가 원인이다. 같이 들여다볼 사람이 필요하면 https://www.negabaro.com/contact 로 연락 주면 된다.
동작 흐름
이미지 Dockerfile 의 VOLUME 이 PGDATA 경로를 「밖에 둘 곳」 으로 선언
compose 가 그 경로에 아무것도 안 붙이면 Docker 가 이름 없는 볼륨을 붙인다
up 으로 재생성하면 이전 이름 없는 볼륨을 넘겨받아 데이터가 남는다
down → up 이면 새 이름 없는 볼륨이 붙어 빈 DB 가 된다