Docker Compose 백업·복원: DB와 업로드 파일을 함께 되살리는 실습
AI Editter
Compose 파일과 DB 볼륨만 복사해 두었다고 서비스 전체를 복원할 수 있는 것은 아닙니다. DB가 첨부파일 경로를 저장하는 앱이라면 업로드 파일도 같은 업무 시점으로 맞아야 합니다. 이미지 버전과 환경 설정, 외부 저장소 의존성도 필요합니다.
이 글은 PostgreSQL과 업로드 디렉터리를 사용하는 소규모 앱의 논리 백업 연습입니다. 명령 예시는 Linux Bash 기준입니다. 바이너리 덤프를 셸 리디렉션할 때 다른 셸의 인코딩·출력 동작을 그대로 가정하지 않습니다.
compose.yaml만 보관해서 복원할 수 있는가
Compose 파일은 서비스 구성을 설명하지만 DB 데이터와 사용자가 올린 파일을 대신 보관하지 않습니다. 필요한 것은 실행할 이미지 버전, 구성 파일, 비밀정보의 안전한 복원 경로, DB 백업, 업로드 파일과 그 시점입니다. 새 서버에서 같은 명령이 성공해도 빈 볼륨으로 뜨면 서비스 데이터는 복원되지 않은 것입니다. 아래 실습에서는 별도 프로젝트 이름으로 복원하고 원본 파일과 실제 조회 결과를 대조합니다.
먼저 데이터가 실제 어디에 있는지 확인
docker compose config와 컨테이너 마운트 정보를 확인하되, 비밀 환경값이 출력에 포함될 수 있으므로 결과를 공개하지 않습니다. 이름 있는 볼륨, bind mount, 외부 스토리지를 구분합니다.
| 구성 | 보관할 것 |
|---|---|
| PostgreSQL | 일관된 DB 백업과 필요한 역할 정보 |
| 업로드 | 실제 파일과 권한 |
| 앱 이미지 | 재사용 가능한 정확한 버전·digest |
| Compose | 서비스·볼륨·네트워크 정의 |
| 비밀값 | 승인된 비밀 저장소의 복구 경로 |
볼륨의 생명주기와 백업 방식은 Docker 볼륨 문서를 참고합니다. 실행 중인 PostgreSQL 데이터 디렉터리를 일반 파일처럼 tar로 묶는 것만으로 일관된 DB 백업이 된다고 생각하지 않습니다.
DB와 파일의 시점을 맞추는 현실적인 방법
소규모 서비스라면 유지보수 시간에 앱·워커의 쓰기를 멈춘 뒤 DB 덤프와 업로드 사본을 만드는 방식이 이해하기 쉽습니다. 웹 요청만 막고 백그라운드 워커가 계속 파일을 만들고 있지 않은지 확인합니다.
장시간 중지가 어렵다면 DB 로그·스토리지 스냅샷·앱의 파일 커밋 규칙 등을 조합한 별도 설계가 필요합니다. 덤프 완료 시각과 파일 복사 완료 시각이 다르다는 사실을 기록하는 것만으로 일관성이 보장되지는 않습니다.
pg_dump로 논리 백업 생성
Compose 서비스 이름이 db, DB와 사용자가 app인 예시입니다. 실제 이름과 권한으로 바꿉니다.
mkdir -p ./backup-set
docker compose exec -T db \
pg_dump -U app -d app -Fc > ./backup-set/app.dump
명령 종료 코드를 확인하고 파일 크기만으로 성공을 판정하지 않습니다. 인증은 승인된 방식으로 제공하고 암호를 명령줄에 직접 쓰지 않습니다. pg_dump 버전과 서버 버전 호환도 확인합니다.
pg_dump는 DB 단위 백업이며 클러스터 전역 역할 등은 별도 고려가 필요합니다. PostgreSQL pg_dump 문서를 기준으로 필요한 객체 범위를 확인합니다.
동일한 백업 세트에 업로드 사본과 이미지 식별자, DB·도구 버전, 백업 기준시각, 파일 검증값을 함께 보관합니다. 실제 비밀 파일을 공개 저장소에 추가하지 않습니다.
별도 Compose 프로젝트로 복원
복원 시험은 새 DB와 새 업로드 위치를 사용합니다. 프로젝트 이름만 바꿔도 명시적 볼륨 이름·external 볼륨·bind mount는 원본을 공유할 수 있으므로 실제 마운트 대상을 반드시 확인합니다.
새 시험 DB가 비어 있고 필요한 사용자와 확장이 준비됐다는 전제에서 다음 형태로 복원할 수 있습니다.
docker compose -p restore-test exec -T db \
pg_restore -U app -d app --no-owner --exit-on-error --single-transaction \
< ./backup-set/app.dump
시험용 Compose 설정을 선택하는 경로와 프로젝트가 맞는지 먼저 확인합니다. --no-owner를 쓰면 소유권 복원 방식이 달라지므로 원래 소유자·권한을 보존해야 하는 환경에는 그대로 적용하지 않습니다. 대용량 복원과 확장 기능은 트랜잭션 옵션의 적용 가능성도 검토합니다.
DB와 파일을 연결해서 검산
| 검사 | 통과 기준 |
|---|---|
| 핵심 테이블 건수 | 백업 기준값과 일치 |
| 최근 거래 | 백업 시점까지 존재 |
| 첨부 연결 | DB 경로에 실제 파일 존재 |
| 파일 내용 | 대표 파일 해시·열기 성공 |
| 신규 쓰기 | 새 행·파일 생성과 조회 정상 |
| 예약 작업 | 시험 환경에서 필요한 동작만 |
첨부가 1,000개라면 파일 수도 무조건 1,000개여야 하는 것은 아닙니다. 축소 이미지·임시 파일 등 앱의 저장 규칙에 따라 대조 기준을 정합니다. DB에 기록된 원본 파일이 실제로 존재하는지는 직접 확인합니다.
백업 완료와 복원 완료를 따로 기록
덤프와 파일 생성 성공, 별도 저장소 전송 성공, 복원 시험 성공을 각각 남깁니다. 백업 세트의 해시를 확인하면 전송 중 손상을 찾는 데 도움이 되지만, 앱 호환성까지 증명하지는 않습니다.
시험이 끝난 뒤 원본과 시험 볼륨을 정확히 구분해 정리합니다. docker compose down -v 같은 명령을 어느 프로젝트에서 실행하는지 모르면 데이터 볼륨을 삭제할 수 있으므로 일반 정리 명령처럼 사용하지 않습니다.
다음 복원 담당자가 알아야 할 것은 덤프 파일 위치뿐 아니라 이미지 버전, 비밀값 복구, 쓰기 중지 기준, 검산 방법입니다. 이 네 가지를 백업 세트와 연결해 보관해야 실제 장애 때 시간을 줄일 수 있습니다.
관련 절차: Docker 용량 부족 해결: 로그·캐시 정리와 볼륨 보존 방법 · NetBox Docker 구축: 4.6 버전 고정·보안·백업·업그레이드