# [Docker Compose 실습] PostgreSQL 볼륨과 초기화 다루기
- PostgreSQL 볼륨과 초기화 다루기 ← 현재 문서
DB 컨테이너에서 가장 중요한 것은 데이터가 언제 유지되고 언제 사라지는지 아는 것이다. 앱 컨테이너는 다시 빌드하고 다시 띄우면 된다. 하지만 DB 데이터는 실수로 지우면 복구하기 어렵다.
이번 실습의 목표는 postgres_data 볼륨, schema.sql 초기화, down -v의 의미를 정확히 구분하는 것이다.
현재 DB 볼륨 구조
현재 Compose 파일은 PostgreSQL 데이터 디렉터리를 named volume에 연결한다.
db:
volumes:
- postgres_data:/var/lib/postgresql/data
- ./schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
volumes:
postgres_data:
첫 번째 줄은 DB 데이터 보존용이다.
- postgres_data:/var/lib/postgresql/data
두 번째 줄은 초기화 SQL 주입용이다.
- ./schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
둘은 역할이 완전히 다르다. postgres_data는 DB가 실제 데이터를 쓰는 곳이고, schema.sql은 데이터 디렉터리가 비어 있을 때 처음 실행되는 초기화 파일이다.
볼륨 목록 확인
Compose를 한 번 실행한 뒤 볼륨을 확인한다.
docker volume ls
프로젝트 이름을 discodeit으로 고정했다면 볼륨 이름은 다음처럼 보일 수 있다.
discodeit_postgres_data
discodeit_app_storage
볼륨 상세 정보는 다음 명령으로 본다.
docker volume inspect discodeit_postgres_data
여기서 실제 마운트 위치를 볼 수 있지만, 보통 직접 수정하지 않는다. Docker가 관리하는 저장소로 생각하면 된다.
schema.sql이 다시 실행되지 않는 이유
PostgreSQL 컨테이너는 처음 시작할 때 데이터 디렉터리가 비어 있으면 초기화 과정을 수행한다. 이때 /docker-entrypoint-initdb.d 아래의 SQL 파일을 실행한다.
하지만 postgres_data 볼륨에 이미 DB가 만들어져 있으면 초기화 단계가 생략된다. 그래서 schema.sql을 수정한 뒤 컨테이너를 재시작해도 변경사항이 자동 반영되지 않는다.
상황별로 선택지가 다르다.
| 상황 | 처리 |
|---|---|
| 처음부터 새 DB로 다시 만들고 싶다 | docker compose down -v 후 다시 up |
| 기존 데이터를 유지하고 스키마만 바꾸고 싶다 | 직접 SQL 실행 또는 마이그레이션 도구 사용 |
| 실수로 볼륨을 지우면 안 된다 | down -v 금지 |
개발용 DB를 완전히 초기화하기
학습용 데이터라서 지워도 된다면 다음 순서로 초기화한다.
docker compose down -v
docker compose up -d
첫 번째 명령은 컨테이너, 네트워크, named volume을 함께 삭제한다. 두 번째 명령은 새 볼륨을 만들고 PostgreSQL 초기화를 다시 수행한다.
down -v는 DB 파일을 지운다. 로컬 실습 데이터처럼 잃어도 되는 경우에만 사용한다.
기존 볼륨을 유지하고 SQL 확인하기
DB 컨테이너가 떠 있다면 내부에서 psql을 실행할 수 있다.
docker compose exec db sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt"'
테이블 목록이 보이면 DB 접속과 초기 스키마가 정상이다.
특정 테이블의 row 수를 확인하려면 다음처럼 실행한다.
docker compose exec db sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "select count(*) from users;"'
테이블 이름은 실제 schema.sql에 맞게 바꾼다.
백업 후 초기화하기
초기화가 필요하지만 현재 데이터를 보관하고 싶다면 먼저 덤프를 만든다.
docker compose exec db sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > backup.sql
그다음 개발용 볼륨을 삭제하고 다시 띄운다.
docker compose down -v
docker compose up -d
복원은 새 DB가 떠 있는 상태에서 수행한다.
docker compose exec -T db sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB"' < backup.sql
PowerShell에서는 리다이렉션 인코딩이나 경로 문제로 명령이 다르게 동작할 수 있다. 덤프와 복원은 중요한 데이터에 적용하기 전에 작은 테스트 DB로 먼저 확인한다.
DB 포트 노출 판단
DB 컨테이너의 포트 매핑은 선택 사항이다.
db:
ports:
- "${POSTGRES_HOST_PORT:-5432}:5432"
이 설정을 유지하면 호스트의 DB 클라이언트에서 접속하기 쉽다. 예를 들어 IntelliJ Database 탭이나 DBeaver에서 localhost:5432로 접근할 수 있다.
반대로 앱 컨테이너만 DB에 접근하면 된다면 이 설정을 제거해도 된다. Compose 내부 네트워크에서는 db:5432로 통신하기 때문이다.
| 필요 | 권장 |
|---|---|
| 로컬 DB 클라이언트로 직접 접속 | ports 유지 |
| 앱 컨테이너만 DB 사용 | ports 제거 가능 |
| 5432 포트 충돌이 자주 발생 | ${POSTGRES_HOST_PORT:-5432}로 외부 포트 조정 |
체크리스트
-
postgres_data가 DB 데이터 보존용이라는 점을 이해했다. -
schema.sql은 빈 데이터 디렉터리에서만 자동 실행된다는 점을 이해했다. -
docker compose down과docker compose down -v의 차이를 설명할 수 있다. - DB 초기화 전에 백업이 필요한 상황을 구분할 수 있다.
- DB 포트 노출이 앱 내부 통신에 필요한 것은 아니라는 점을 확인했다.
이제 마지막 실습에서 전체 실행과 문제 해결 루틴을 정리한다.