본문 바로가기
프로그램 개발(분석, 설계, 코딩, 배포)/100. 기타

AI | DOCKER DB 휘발성 문제 해결과 삭제 방어

by 3604 2026. 8. 18.
728x90

pgvector에 데이터를 입력 후 docker compose down 하면 입력 데이터가 모두 삭제됨. db volumes을 별도 생성해야 할 것같은데 어떻게 해야 하나?

맞습니다. Docker 컨테이너는 기본적으로 휘발성(Ephemeral) 상태로 동작하기 때문에, 별도의 저장 공간을 지정하지 않고 docker compose down을 실행하면 컨테이너 내부의 데이터가 모두 함께 삭제됩니다.

첨부해주신 image_587730.png를 보면 pgvector/pgvector:pg16 이미지를 기반으로 rag_postgres라는 이름의 컨테이너를 구동 중이신 것으로 확인됩니다. 데이터를 영구적으로 보존(Persistence)하려면 사용 중이신 docker-compose.yml 파일에 Docker Volume(볼륨)을 추가로 매핑해 주어야 합니다.

해결을 위한 구체적인 단계를 안내해 드립니다.

1. docker-compose.yml 파일 수정

PostgreSQL이 데이터를 저장하는 기본 경로인 /var/lib/postgresql/data를 Docker 시스템의 볼륨과 연결해야 합니다. docker-compose.yml 파일을 열고 아래와 같이 volumes 설정을 추가해 주세요.

YAML

version: '3.8' # 사용 중인 버전에 맞게 유지

services:
  # (다른 서비스들... rag_app, llama_server, embedding_server 등)

  rag_postgres: # 현재 작성되어 있는 서비스 이름 (이름은 다를 수 있습니다)
    image: pgvector/pgvector:pg16
    container_name: rag_postgres
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=your_user
      - POSTGRES_PASSWORD=your_password
      - POSTGRES_DB=your_db
    # ✅ 아래 volumes 항목을 추가합니다.
    volumes:
      - pg_vector_data:/var/lib/postgresql/data

# ✅ 파일의 맨 마지막(최상위 레벨)에 volumes 블록을 선언해야 합니다.
volumes:
  pg_vector_data:

💡 코드 설명:

  • volumes: - pg_vector_data:/var/lib/postgresql/data: 컨테이너 내부의 데이터 저장 경로를 Docker가 관리하는 pg_vector_data라는 이름의 볼륨에 연결(마운트)합니다.
  • 최하단 volumes: 선언: Docker 엔진에게 pg_vector_data라는 이름의 볼륨을 실제로 생성하라고 지시합니다.

2. 변경 사항 적용 및 재시작

파일을 저장한 후, 터미널에서 기존 컨테이너를 내리고 다시 올려 볼륨을 생성 및 적용합니다.

Bash

# 1. 기존 컨테이너 중지 및 삭제 (이전에 남아있던 설정 제거)
docker compose down

# 2. 볼륨 설정이 적용된 상태로 백그라운드에서 다시 실행
docker compose up -d

3. 볼륨 생성 확인 (선택 사항)

이제 docker compose down을 하더라도 데이터는 안전하게 보존됩니다. 생성된 볼륨은 아래 명령어로 직접 확인할 수 있습니다.

Bash

# 생성된 도커 볼륨 리스트 확인
docker volume ls

# 특정 볼륨의 상세 정보(실제 호스트 PC 저장 경로 등) 확인
docker volume inspect my-rag-app_pg_vector_data

주의 사항: 만약 데이터베이스를 포함해 볼륨까지 완전히 초기화하고 싶을 때만 docker compose down -v (또는 --volumes) 옵션을 사용하시면 됩니다. 평소에는 docker compose down만 사용하면 데이터가 유지됩니다.

---

 

코드에 문제가 없음에도 docker compose down 실행 후 데이터가 사라졌다면, 볼륨 설정 누락이 아닌 다른 외부적인 요인을 점검해 보아야 합니다. 컨테이너 인프라 및 DB 운영 시 주로 발생하는 원인들은 다음과 같습니다.

1. docker compose down -v 옵션 사용 여부

docker compose down 명령어에 무심코 -v (또는 --volumes) 옵션을 붙여서 실행하셨을 가능성이 있습니다. 이 옵션은 컨테이너를 내리는 것과 동시에 매핑된 Named Volume까지 명시적으로 삭제해 버리므로 내부 데이터가 모두 초기화됩니다.

2. 프로젝트 디렉터리 이름 변경

Docker Compose는 볼륨을 생성할 때 기본적으로 [현재_디렉터리_이름]_[볼륨_이름] 규칙을 사용합니다. 예를 들어 디렉터리 이름이 my-rag-app이라면 볼륨 이름은 my-rag-app_pgdata가 됩니다. 만약 데이터를 입력한 후 프로젝트 폴더의 이름을 변경하고 다시 컨테이너를 띄웠다면, Docker는 새로운 디렉터리 이름으로 완전히 비어있는 새 볼륨을 생성하여 연결합니다.

3. 데이터베이스 트랜잭션 커밋(Commit) 누락

pgvector에 데이터를 INSERT 하거나 애플리케이션(RAG Web App)을 통해 벡터를 입력한 후, 해당 세션에서 COMMIT이 정상적으로 이루어지지 않은 상태에서 컨테이너가 종료되었을 수 있습니다. 애플리케이션 코드나 DB 클라이언트 툴에서 Auto-commit이 활성화되어 있는지 확인이 필요합니다.

4. 권한(Permission) 문제로 인한 임시 파일 저장

드문 경우지만, 컨테이너 내부의 postgres 유저가 마운트된 /var/lib/postgresql/data 디렉터리에 쓰기 권한이 없어, 볼륨 외부의 임시 경로에 데이터를 쓰고 있었을 가능성도 있습니다.

🛠️ 검증 및 해결 방법

현재 볼륨에 데이터가 실제로 남아있는지, 아니면 아예 지워졌는지 다음 명령어로 디버깅해 보실 수 있습니다.

1. 현재 생성된 도커 볼륨 리스트 확인

Bash

docker volume ls | grep pgdata

여기서 my-rag-app_pgdata와 같은 볼륨이 보여야 합니다.

2. 볼륨 내부 데이터 직접 확인 PostgreSQL 컨테이너를 띄우지 않고, 임시 컨테이너를 사용해 볼륨 내부를 들여다볼 수 있습니다.

Bash

# my-rag-app_pgdata 부분은 위 1번에서 확인한 실제 볼륨 이름으로 변경
docker run --rm -v my-rag-app_pgdata:/data alpine ls -al /data

출력 결과에 PG_VERSION, base, global 등의 PostgreSQL 기본 파일과 디렉터리들이 보인다면 데이터 자체는 안전하게 볼륨에 남아있는 상태이며 DB 구동 시점에 데이터를 제대로 읽지 못하는 다른 문제를 찾아야 합니다. 아무것도 없다면 생성 후 데이터가 기록되지 않았거나 삭제된 것입니다.

"docker compose down -v"를 사용했다. 이 명령어를 신규 직원이 사용한 경우 복구 방법이 없나?

안타깝지만 가장 먼저 명확한 사실을 말씀드려야 할 것 같습니다. Docker 자체에는 -v 옵션으로 삭제된 볼륨을 복구하는 '휴지통'이나 '실행 취소(Undo)' 기능이 존재하지 않습니다.

-v (또는 --volumes) 옵션은 도커 데몬에게 "컨테이너를 내리면서 이 컨테이너와 연결된 모든 이름 있는 볼륨(Named Volumes)의 물리적 데이터까지 호스트 디스크에서 완전히 삭제하라"는 명시적인 명령이기 때문입니다.

하지만 도커 자체의 복구 기능이 없을 뿐, 시스템 및 애플리케이션 관점에서는 다음과 같은 우회적인 복구 및 해결 방안을 검토해 볼 수 있습니다.

1. 인프라 스냅샷 또는 백업 확인 (VM / Cloud 환경)

만약 이 시스템이 사내 구축형(On-Premise) 베어메탈 서버가 아니라 AWS EC2, Azure VM, VMware 등의 가상화 환경에서 구동 중이라면, 매일 또는 특정 주기마다 디스크 전체 스냅샷이 생성되도록 구성되어 있을 확률이 높습니다.

  • 조치 방법: 인프라 관리자에게 해당 서버의 가장 최근 디스크 스냅샷(예: AWS EBS Snapshot)이 있는지 확인하고, 스냅샷 시점의 디스크로 롤백하거나 볼륨 경로(/var/lib/docker/volumes/...)만 마운트하여 데이터를 추출할 수 있습니다.

2. RAG 파이프라인의 특성을 활용한 데이터 '재생성' (가장 현실적인 대안)

현재 개발 중이신 시스템이 RAG(검색 증강 생성) 애플리케이션이라는 점에 주목할 필요가 있습니다. 일반적인 관계형 DB의 고객 정보나 결제 내역이 날아간 것이라면 치명적이지만, Vector DB(pgvector)에 저장된 데이터는 대부분 원본 문서(PDF, 텍스트, 사내 규정 등)를 쪼개어(Chunking) 임베딩 모델을 거쳐 생성된 '파생 데이터'입니다.

  • 조치 방법: 원본 문서 파일들이 그대로 남아있다면, 복구를 시도하며 시간을 쏟는 것보다 데이터 수집 및 임베딩 스크립트를 다시 실행하여 Vector DB에 데이터를 새로 적재하는 것이 훨씬 빠르고 확실한 해결책일 수 있습니다.

3. 디스크 복구 도구 사용 (최후의 수단, 권장하지 않음)

명령어 실행 직후에 디스크 쓰기 작업이 거의 일어나지 않은 상태라면, Linux의 파일 시스템 복구 툴(예: extundelete, TestDisk 등)을 사용해 볼륨이 저장되었던 물리적 섹터를 스캔할 수는 있습니다.

  • 하지만 데이터베이스 파일은 여러 조각으로 나뉘어 저장되고 무결성이 매우 중요하기 때문에, 파일 조각을 찾아내더라도 DB가 정상적으로 마운트될 확률은 극히 희박합니다.

💡 향후 동일한 사고를 원천 차단하는 방어 아키텍처

신규 직원의 실수는 언제든 다시 발생할 수 있으므로, 아키텍처 레벨에서 -v 옵션이 무력화되도록 설정하는 것이 좋습니다. docker-compose.yml의 볼륨 설정을 external: true로 변경하면 이 문제를 완벽히 예방할 수 있습니다.

기존 코드:

YAML

volumes:
  pgdata:

변경할 코드:

YAML

volumes:
  pgdata:
    external: true

이렇게 설정하면 해당 볼륨이 docker-compose.yml에 종속된 것이 아니라 '외부에서 독립적으로 관리되는 자산'으로 인식됩니다. 따라서 누군가 docker compose down -v를 입력하더라도, "이 볼륨은 external로 선언되어 있어 삭제할 수 없습니다"라는 에러를 내뿜으며 데이터가 안전하게 보호됩니다. (단, 이 설정을 적용하기 전에 docker volume create pgdata 명령어로 호스트에서 볼륨을 수동으로 먼저 만들어주어야 합니다.)

방어 아키텍처 적용

이번 기회에 데이터를 재생성한 후, 설명해주신 external: true 옵션을 적용하여 볼륨을 안전하게 재구성하는 구체적인 순서를 안내해 드릴까요?

데이터 유실 방지를 위한 external: true 볼륨 구성은 엔터프라이즈 환경에서 필수적으로 적용하는 안전장치 중 하나입니다.

기존 환경을 정리하고 안전하게 독립된 볼륨으로 RAG 데이터베이스를 재구성하는 전체 과정을 단계별로 안내해 드립니다.

1단계: 기존 컨테이너 환경 정리

먼저 현재 실행 중이거나 남아있는 컨테이너와 네트워크를 완전히 정리하여 충돌을 방지합니다.

Bash

# 실행 중인 프로젝트 컨테이너 중지 및 삭제
docker compose down

2단계: 독립적인 외부 도커 볼륨 생성

Docker Compose 파일에 종속되지 않는 완전히 독립적인 도커 볼륨을 호스트 시스템에 직접 생성합니다. 이름은 관리하기 쉽게 rag_pgdata_safe로 지정해 보겠습니다.

Bash

# 독립형(External) 볼륨 생성
docker volume create rag_pgdata_safe

# 생성된 볼륨 확인
docker volume ls | grep rag_pgdata_safe

3단계: docker-compose.yml 파일 수정

생성한 외부 볼륨을 PostgreSQL 컨테이너에 연결하도록 설정 파일을 수정합니다.

  • 서비스(db) 항목: 마운트되는 볼륨 이름을 변경합니다.
  • 최하단(volumes) 항목: 새로 만든 볼륨 이름을 넣고 external: true 옵션을 부여합니다.

YAML

# ... (상단 생략) ...

  # 2. Vector DB (PostgreSQL + pgvector)
  db:
    image: pgvector/pgvector:pg16
    container_name: rag_postgres
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: ragdb
    ports:
      - "5432:5432"
    volumes:
      # ✅ 수정: 새로 만든 외부 볼륨 이름으로 매핑
      - rag_pgdata_safe:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - rag-network

# ... (중략) ...

# ✅ 수정: 파일 최하단 볼륨 정의 변경
volumes:
  rag_pgdata_safe:
    external: true

4단계: 시스템 재가동 및 데이터 재생성

수정된 설정을 바탕으로 시스템을 다시 구동하고 파생 데이터를 다시 적재합니다.

Bash

# 컨테이너 백그라운드 실행
docker compose up -d

# 정상 구동 확인
docker ps

컨테이너가 모두 정상적으로 Up 상태가 되었다면, 기존에 사용하셨던 데이터 수집(Ingestion) 및 임베딩 스크립트를 실행하여 Vector DB에 데이터를 다시 채워 넣습니다.

5단계: 방어 메커니즘 동작 확인 (안전성 테스트)

데이터 적재가 완료된 후, 신규 직원이 실수로 -v 옵션을 사용했을 때 시스템이 데이터를 어떻게 보호하는지 직접 테스트해 볼 수 있습니다.

Bash

# 실수로 -v 옵션을 포함하여 삭제 명령어를 실행한 상황 가정
docker compose down -v

결과 화면: 이 명령어를 실행하더라도 컨테이너와 네트워크만 삭제될 뿐, 도커 엔진은 다음과 같은 경고 메시지와 함께 볼륨 삭제를 거부합니다.

WARNING: Volume rag_pgdata_safe is external, skipping

이제 데이터베이스 볼륨은 docker-compose 명령어의 생명주기에서 완전히 벗어나 안전하게 격리되었습니다. 향후 데이터베이스를 띄울 때는 다시 docker compose up -d만 실행하시면 보존된 데이터를 그대로 물고 올라옵니다.

728x90