2026/06/15

Docker Compose 서비스 백업 및 복구 가이드

서론

Docker Compose 로 Self-Hosted 서비스를 운영할 때 가장 중요한 것은 데이터 백업입니다. 서버 장애, 디스크 손상, 실수로 인한 데이터 삭제 — 언제든 발생할 수 있는 상황들에 대비하기 위해 체계적인 백업 전략이 필요합니다.

이번 글에서는 Docker Compose 기반의 Self-Hosted 인프라(PostgreSQL, n8n, Ghost Blog 등)에 대한 백업 자동화, 복구 절차, 그리고 주의사항 을 교육 자료 형식으로 정리했습니다. 실제 운영 중인 서비스의 경로나 비밀번호는 제외하고, 누구나 적용 가능한 일반적인 가이드로 작성했습니다.


백업 대상과 중요도

Docker Compose 환경에서 백업해야 할 대상은 크게 세 가지로 나뉩니다.

  • 데이터베이스 — PostgreSQL, SQLite 등 구조화된 데이터 (최고 중요도)
  • 애플리케이션 데이터 — 워크플로우, 블로그 콘텐츠, 미디어 파일 (높은 중요도)
  • 설정 파일 — Nginx reverse proxy, SSL 인증서, 서비스 설정 (보통 ~ 높은 중요도)
서비스 Volume 경로 백업 방식 중요도
PostgreSQL./data/postgresVACUUM FULL → pg_dumpall🔴 최고
n8n./data/n8nVACUUM → tar (*.log 제외)🔴 최고
Ghostcontent/tar 압축🟡 높음
Certbot./data/certbottar 압축🟡 높음
Nginx./nginx/conftar 압축🟢 보통
SearXNG./data/searxngtar 압축🟢 보통

백업 스크립트 구성

백업 스크립트는 bash 로 작성하며, 각 서비스의 특성에 맞는 백업 전략을 적용합니다. 핵심은 데이터 무결성 보장 입니다.

PostgreSQL — SQL Dump 방식 (핵심)

PostgreSQL 은 tar 로 직접 덤프하면 안 됩니다. WAL 파일이 섞여 복구 시 데이터 손상이 발생할 수 있으므로, 반드시 pg_dumpall 명령을 통해 SQL 덤프를 생성한 후 gzip 으로 압축합니다.

# VACUUM FULL: 데이터베이스 파일 크기 축소
docker exec postgres psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -c "VACUUM FULL;"

# pg_dumpall: 전체 SQL 덤프 생성
docker exec postgres pg_dumpall -U ${POSTGRES_USER} > backups/pg_all_${DATE}.sql

# gzip 압축
gzip -f backups/pg_all_${DATE}.sql
VACUUM FULL 은 데이터베이스 파일의 물리적 크기를 축소하여 백업 파일 크기를 최소화합니다. pg_dumpall 은 서비스 중단 없이 백업 가능합니다.

n8n — SQLite VACUUM + tar 방식

n8n 은 SQLite 를 사용하므로 PostgreSQL 과 다른 전략이 필요합니다. 컨테이너를 중지한 후 sqlite3 VACUUM 명령으로 데이터베이스 파일을 최적화하고, tar 로 압축합니다. 로그 파일은 백업에서 제외하여 용량을 절약합니다.

# 컨테이너 중지
docker stop n8n

# SQLite VACUUM: DB 파일 최적화
sqlite3 ./data/n8n/database.sqlite "VACUUM;"

# 컨테이너 재시작
docker start n8n
sleep 2

# tar 압축 (*.log 제외)
tar -czf backups/n8n_${DATE}.tar.gz \
    --exclude='*.log' \
    -C ./data n8n

기타 서비스 — tar 압축

Ghost 콘텐츠, Certbot SSL 인증서, Nginx 설정, SearXNG 설정 등은 tar.gz 로 압축하는 단순한 방식이 적합합니다.

# Ghost 블로그 콘텐츠
tar -czf backups/ghost_${DATE}.tar.gz \
    -C ~/Developer/GhostBlog content

# Certbot SSL 인증서
tar -czf backups/certbot_${DATE}.tar.gz \
    -C . data/certbot

# Nginx 설정
tar -czf backups/nginx_conf_${DATE}.tar.gz \
    -C . nginx/conf

자동 백업 설정

  • 스크립트에 실행 권한 부여: chmod +x backup.sh
  • cron 에 등록하여 매일 새벽 자동 실행
  • 백업 로그를 파일로 출력하여 이력 추적
# 실행 권한 부여
chmod +x ~/Developer/WebServer/backup.sh

# crontab 편집 — 매일 새벽 3:30 자동 백업
crontab -e

# 추가할 라인:
30 3 * * * /Users/yourname/Developer/WebServer/backup.sh

cron 등록 후 확인: crontab -l | grep backup

백업 로그 실시간 확인: tail -f backups/backup.log


복구 절차

백업의 가치는 복구할 때才知道입니다. 정기적인 복구 테스트가 필수적입니다.

# 사용법
./restore.sh <backup_date> [service]

# 전체 복구
./restore.sh 20250614_030000 all

# 개별 서비스만 복구
./restore.sh 20250614_030000 pg
./restore.sh 20250614_030000 n8n
./restore.sh 20250614_030000 ghost

PostgreSQL 복구

  • 컨테이너 중지: docker stop postgres
  • SQL 덤프 압축 해제: gunzip -kf backups/pg_all_YYYYMMDD_HHMMSS.sql.gz
  • 데이터 적용: docker exec -i postgres psql -U ${USER} < backups/pg_all_*.sql
  • 임시 SQL 파일 삭제: rm backups/pg_all_*.sql
  • 컨테이너 재시작: docker start postgres

n8n 복구

  • 컨테이너 중지: docker stop n8n
  • 데이터 복구: tar -xzf backups/n8n_YYYYMMDD_HHMMSS.tar.gz -C ./WebServer
  • 컨테이너 재시작: docker start n8n (로그 파일은 자동 재생성됨)

Ghost 복구

  • 컨테이너 중지: docker stop ghost
  • 콘텐츠 복구: tar -xzf backups/ghost_YYYYMMDD_HHMMSS.tar.gz -C ~/Developer/GhostBlog
  • 컨테이너 재시작: docker start ghost

Nginx / Certbot / SearXNG 복구

설정 파일 복구는 tar 압축 해제 후 서비스 재시작만 필요합니다.

# Certbot 복구 후 Nginx 재시작
tar -xzf backups/certbot_${DATE}.tar.gz -C ./WebServer
docker restart nginx

# Nginx 설정 복구
tar -xzf backups/nginx_conf_${DATE}.tar.gz -C ./WebServer
docker restart nginx

# SearXNG 복구
tar -xzf backups/searxng_${DATE}.tar.gz -C ./WebServer
docker restart searxng

백업 파일 구조

backups/
├── backup.log                          # 백업 실행 로그 (누적 유지)
├── pg_all_20250614_030000.sql.gz      # PostgreSQL 전체 dump
├── n8n_20250614_030000.tar.gz         # n8n 데이터 (*.log 제외)
├── ghost_20250614_030000.tar.gz       # Ghost 콘텐츠
├── certbot_20250614_030000.tar.gz     # SSL 인증서
├── nginx_conf_20250614_030000.tar.gz  # Nginx 설정
├── searxng_20250614_030000.tar.gz     # SearXNG 설정
└── money_20250614_030000.tar.gz       # 기타 앱 데이터

백업 파일은 30일 보관 후 스크립트가 자동으로 삭제합니다. 디스크 공간을 효율적으로 관리하려면 retention 기간을 환경에 맞게 조정하세요.


주의 사항과 모범 사례

PostgreSQL — tar 로 직접 덤프 금지

가장 중요한 규칙입니다. PostgreSQL 데이터 디렉토리를 tar 로 백업하면 WAL 파일이 포함되고, 복구 시 데이터 손상이 발생할 수 있습니다. 항상 pg_dumpall 또는 pg_dump 명령을 사용하세요.

n8n — 컨테이너 중지 후 백업

n8n 은 SQLite 를 사용하므로 컨테이너 실행 중 백업하면 데이터 손상이 가능합니다. 반드시 컨테이너를 중지한 후 VACUUM → tar 순서로 진행하세요.

백업 디렉토리는 Git 에서 제외

백업 파일은 절대 Git 에 커밋하지 마세요. 민감한 데이터가 포함될 수 있고, 리포지토리 용량을 급증시킵니다.

# .gitignore
backups/

원격 저장소 동기화

로컬 백업만으로는 디스크 손상 시 복구가 불가능합니다. 백업 파일을 S3, Dropbox, Google Drive 등의 원격 저장소와 동기화하는 것이 안전합니다. rsync 또는 rclone 을 활용하세요.

정기적인 복구 테스트

백업이 성공했다고 믿기 전에 반드시 복구 테스트를 해보세요. 테스트 환경에서 백업 파일을 복구하고 데이터가 제대로 읽히는지 확인하는 것이 가장 확실한 검증 방법입니다.


문제 해결

백업이 실패할 때

  • 로그 확인: tail backups/backup.log
  • Docker 컨테이너 상태: docker ps
  • 디스크 공간: df -h
  • 특정 서비스 백업이 실패하면 해당 경로의 존재 여부를 확인

cron 이 실행되지 않을 때 (macOS)

  • cron 서비스 확인: launchctl list | grep cron
  • crontab 확인: crontab -l
  • 시스템 로그: log show --predicate 'eventMessage contains "cron"' --last 1h

복구가 실패할 때

  • 백업 파일 존재 확인: ls backups/
  • 파일 압축 해제 테스트: tar -tzf backups/XXX.tar.gz
  • 컨테이너 상태 확인: docker ps -a
  • 복구 스크립트를 단계별로 수동 실행하여 문제 지점 파악

마무리

백업은 '언젠가 해야 할 일' 이 아니라 '이미 해둔 일' 이어야 합니다. 오늘 백업 스크립트를 작성하고 cron 에 등록하면, 내일의 당신은 그 선택을 감사할 것입니다.

Docker Compose 환경에서는 스크립트 한 줄로 모든 서비스의 데이터를 보호할 수 있습니다. 복구 테스트를 잊지 마세요. 백업의 진짜 가치는 복구할 때 확인됩니다.

댓글 없음:

댓글 쓰기

SK하이닉스 ADR 상장 이후 한국 증시 급락의 원인 분석

분류: 증시분석 SK하이닉스 ADR 상장 이후 한국 증시 급락의 원인 분석 지난 7월 10일, SK하이닉스가 미국 나스닥에 미국주식예탁증서(ADR)를 상장했다. 공모가 149달러로 상장한 하이닉스 ADR은 첫 거래일인 13일 기준 약 168달...