
데이터가 사라진 정적 속에서 깨닫는 백업의 가치
새벽 2시, 서버 알람이 울려 급히 터미널에 접속했어요. 평소처럼 명령어를 입력했는데, 갑자기 데이터베이스 컨테이너가 작동을 멈췄어요. 당황해서 명령어를 이것저것 입력하다가 실수로 볼륨(Volume)까지 모두 삭제하는 명령어를 실행하고 말았어요. 순식간에 지난 1년간 쌓아온 고객 데이터와 설정값들이 허공으로 사라지는 순간이었어요.
도커 컴포즈를 사용하는 환경은 관리가 매우 편리하지만, 그 편리함 뒤에는 데이터 휘발성이라는 무서운 함정이 숨어 있어요. 컨테이너는 언제든 삭제되고 재생성될 수 있는 존재예요. 만약 우리가 서비스 블록(services block)에 정의된 데이터 저장 공간을 별도로 관리하지 않는다면, 컨테이너가 재시작되는 순간 모든 데이터는 영원히 사라져요.
단순히 “백업을 해두었으니 괜찮겠지”라는 생각은 위험해요. 정작 데이터가 깨졌을 때, 그 백업 파일이 제대로 작동하는지 확인해본 적이 있나요? 백업은 파일이 존재하는 것이 아니라, 언제든 완벽하게 되돌릴 수 있는 상태를 의미해요. 오늘 이 글을 통해 컴포즈 services 백업을 어떻게 설계하고, 실제 재난 상황에서 어떻게 데이터를 되살려내는지 실무적인 방법을 모두 알려드릴게요.
이 글을 끝까지 읽고 나면 다음과 같은 능력을 갖추게 돼요.
- 백업해야 할 핵심 대상(볼륨, 설정 파일, DB)을 정확히 구분할 수 있어요.
- 수동 작업 없이 매일 자동으로 실행되는 백업 스크립트를 작성할 수 있어요.
- 데이터 유실 시 당황하지 않고 서비스를 정상화하는 복구 절차를 익혀요.
- 백업 파일이 진짜 쓸모 있는지 검증하는 훈련법을 알게 돼요.
백업 시작 전 반드시 챙겨야 할 체크리스트
무작정 스크립트를 짜기 전에, 무엇을 어떤 방식으로 보호할지 결정하는 과정이 필요해요. 컴포즈 환경에서는 단순히 파일만 복사한다고 해서 모든 것이 해결되지 않아요. 데이터베이스의 경우, 파일이 디스크에 써지는 도중에 복사를 시도하면 데이터가 깨질 수 있기 때문이에요.
백업 대상의 종류와 특징
우리가 보호해야 할 대상은 크게 세 가지로 나눌 수 있어요. 첫째는 도커 볼륨(Docker Volume)에 저장된 실제 데이터이고, 둘째는 컨테이너의 동작을 결정하는 docker-compose.yml과 .env 같은 설정 파일이에요. 마지막으로는 데이터베이스 엔진이 생성하는 로그와 인덱스 파일들이에요.
이 대상들을 어떻게 백업할지는 서비스의 성격에 따라 달라져야 해요. 아래 표를 보고 현재 운영 중인 환경에 가장 적합한 방식을 선택해 보세요.
| 백업 방식 | 대상 | 장점 | 단점 |
|---|---|---|---|
| 파일 압축 방식 | 볼륨 및 설정 파일 | 구현이 매우 쉽고 빠름 | DB 가동 중 실행 시 데이터 손상 위험 |
| DB 덤프 방식 | 데이터베이스 내부 데이터 | 데이터 무결성 보장 | 백업 파일 크기가 커질 수 있음 |
| 스냅샷 방식 | 클라우드/스토리지 전체 | 복구 속도가 매우 빠름 | 비용이 높고 세밀한 제어 어려움 |
가장 권장하는 방법은 하이브리드 방식이에요. 설정 파일은 파일 압축 방식으로, 데이터베이스는 전용 덤프 도구(mysqldump, pg_dump 등)를 사용하여 별도로 관리하는 것이 가장 안전해요.
준비물 및 환경 체크
실전으로 들어가기 전에 다음 환경이 갖춰져 있는지 꼭 확인해 주세요.
- 백업 파일을 저장할 별도의 외부 스토리지 (로컬 디스크가 아닌 AWS S3, 별도 NAS 등)
- 백업 스크립트를 실행할 cron 또는 systemd timer 권한
- 데이터베이스 컨테이너 내부로 명령어를 전달할 수 있는 docker exec 권한
- 충분한 디스크 여유 공간 (백업 파일 크기의 최소 2배 이상)
실전 컴포즈 services 백업 및 복구 프로세스
이제 본격적으로 백업 스크립트를 구성하고, 실제로 데이터가 사라졌을 때 어떻게 복구하는지 단계별로 살펴볼게요. 이 과정은 단순히 명령어를 입력하는 것을 넘어, 데이터의 일관성을 유지하는 데 초점을 맞춰야 해요.
STEP 1. 백업 대상 식별하기
컴포즈 파일에서 어떤 데이터가 어디에 저장되는지 아는 것이 첫걸음이에요. `docker inspect` 명령어를 사용하면 특정 서비스가 사용하는 볼륨의 정확한 위치를 찾을 수 있어요.
예를 들어, `db_data`라는 볼륨을 사용하는 서비스를 확인하려면 다음과 같이 입력해요. docker inspect [컨테이너_이름] | grep -A 10 Mounts
이 명령어를 통해 호스트 시스템의 어느 경로에 데이터가 매핑되어 있는지, 혹은 도커가 관리하는 내부 경로가 어디인지 정확히 파악할 수 있어요. 이 경로를 모르면 백업을 시도할 때 엉뚱한 파일을 복사하게 될 수도 있어요.
STEP 2. 데이터베이스 덤프 스크립트 작성하기
데이터베이스는 단순히 파일을 복사하면 안 돼요. 데이터가 디스크에 기록되는 도중에 복사가 일어나면 파일이 깨지기 때문이죠. 그래서 반드시 컨테이너 내부의 전용 도구를 사용해야 해요.
다음은 MySQL 서비스를 위한 백업 스크립트 예시예요. 이 내용을 `.sh` 파일로 만들어 관리하면 좋아요.
스크립트 내에 백업 파일의 이름을 $(date +%Y%m%d_%H%M%S)와 같이 타임스탬프를 포함하면 파일이 덮어씌워지는 것을 막을 수 있어요.
#!/bin/bash
# 변수 설정
BACKUP_DIR="/mnt/backups/db"
CONTAINER_NAME="my_db_container"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/db_backup_$TIMESTAMP.sql"
# DB 덤프 실행
docker exec $CONTAINER_NAME mysqldump -u root -p'password' --all-databases > $BACKUP_FILE
# 오래된 백업 삭제 (7일 경과)
find $BACKUP_DIR -type f -mtime +7 -name "*.sql" -delete
이 스크립트는 데이터베이스의 모든 내용을 SQL 파일로 추출하고, 용량 관리를 위해 7일이 지난 파일은 자동으로 삭제하도록 설계되었어요.
STEP 3. 설정 파일 및 볼륨 자동 백업 구성
데이터베이스 외에 설정 파일(.env, docker-compose.yml)과 일반 파일 볼륨은 `tar` 명령어를 사용하여 압축하는 것이 효율적이에요. 이 작업은 데이터베이스 덤프가 끝난 직후에 수행하도록 배치하는 것이 좋아요.
전체 백업 과정을 자동화하기 위해 crontab에 등록하는 방법은 다음과 같아요. 매일 새벽 3시에 백업이 수행되도록 설정해 볼게요.
# crontab -e 입력 후 아래 내용 추가
0 3 * * * /home/user/scripts/full_backup.sh
STEP 4. 데이터 복구 실습 (재난 상황 가정)
가장 중요한 단계예요. 이제 컨테이너가 완전히 삭제되었다고 가정하고, 백업 파일로부터 서비스를 정상화하는 과정을 따라 해 보세요.
[복구 시나리오: MySQL 서비스]
- 환경 재구축: 먼저 기존의 `docker-compose.yml` 파일을 준비해요. 데이터가 담길 볼륨은 새로 생성되어야 해요.
- 컨테이너 기동:
docker-compose up -d를 실행하여 빈 데이터베이스 컨테이너를 띄워요. - 데이터 주입: 준비된 덤프 파일을 컨테이너 내부로 밀어 넣어줘요.
cat db_backup_20240520.sql | docker exec -i my_db_container mysql -u root -p'password' - 무결성 검증: 컨테이너에 접속하여 실제 테이블과 데이터가 잘 들어왔는지
SELECT문으로 확인해요.
이 과정을 직접 해보지 않으면, 정작 사고가 났을 때 명령어 하나가 기억나지 않아 패닉에 빠질 수 있어요. 복구는 눈으로 하는 것이 아니라 손으로 하는 것임을 명심하세요.
복구 시 가장 흔한 실수는 기존 컨테이너가 실행 중인 상태에서 덤프 파일을 덮어씌우려고 하는 것이에요. 반드시 컨테이너가 정상적으로 올라온 상태에서 데이터 주입 명령을 수행해야 해요.
자주 하는 실수와 해결법
백업과 복구를 운영하다 보면 누구나 한 번쯤 실수를 하게 돼요. 경험 많은 운영자들도 놓치기 쉬운 결정적인 부분들을 정리했어요.
- ❌ 실행 중인 DB 파일 직접 복사 → 왜 발생하는가? 데이터가 디스크에 기록되는 도중에 복사되어 파일이 깨져요. → ✅ 해결법: 반드시
mysqldump나pg_dump같은 전용 덤프 도구를 사용하세요. - ❌ 설정 파일(.env) 백업 누락 → 왜 발생하는가? 데이터만 중요하다고 생각해서 환경 변수 파일을 잊어버려요. → ✅ 해결법: 서비스 구성 전체를 포함하는 프로젝트 폴더 전체를 백업 대상에 넣으세요.
- ❌ 백업 파일의 용량 확인 미비 → 왜 발생하는가? 백업 스크립트가 에러가 나도 결과물(0바이트 파일)이 생성되어 성공한 줄 알아요. → ✅ 해결법: 스크립트 마지막에 파일 크기가 0보다 큰지 확인하는 조건문을 추가하세요.
- ❌ 로컬 디스크에만 백업 보관 → 왜 발생하는가? 관리가 편하기 때문이에요. → ✅ 해결법: 서버 자체가 고장 나면 백업도 같이 사라져요. 반드시 외부 스토리지나 클라우드로 전송하세요.
- ❌ 복구 테스트 생략 → 왜 발생하는가? 백업이 잘 되고 있으니 믿기 때문이에요. → ✅ 해결법: 한 달에 한 번은 반드시 별도의 테스트 서버에서 복구 시나리오를 실행해 보세요.
자주 묻는 질문
Q. 백업은 얼마나 자주 해야 하나요?
서비스의 데이터 변화량에 따라 달라요. 결제가 빈번한 쇼핑몰이라면 매시간, 단순 게시판이라면 매일 한 번 정도면 적당해요. 중요한 것은 데이터가 유실되었을 때 “어느 시점까지 되돌릴 수 있는가”라는 기준(RPO)을 먼저 세우는 것이에요.
Q. 컨테이너를 중지하고 백업해야 하나요?
가장 안전한 방법은 서비스를 잠시 중지(Cold Backup)하는 것이지만, 운영 중인 서비스라면 불가능하죠. 이럴 때는 데이터베이스 덤프 도구를 사용하면 컨테이너를 끄지 않고도 안전하게 데이터를 뽑아낼 수 있어요.
Q. 도커 볼륨 경로를 직접 찾아가서 압축하면 안 되나요?
할 수는 있지만 권장하지 않아요. 도커 엔진이 볼륨을 관리하는 방식이나 권한 문제로 인해 복구 시 파일 권한이 꼬일 위험이 크기 때문이에요. 가능하면 docker cp나 전용 덤프 명령어를 사용하는 것이 훨씬 깔끔해요.
Q. 백업 파일 용량이 너무 커서 관리가 힘들어요.
압축 알고리즘을 강화하거나, 오래된 백업을 자동으로 삭제하는 로직을 꼭 넣으세요. 또한, 텍스트 기반의 SQL 덤프 파일은 gzip 등을 사용하면 용량을 70~80% 이상 획기적으로 줄일 수 있어요.
안정적인 운영을 위한 마지막 약속
백업은 단순히 기술적인 작업이 아니라, 서비스 운영자의 책임감을 보여주는 지표예요. 데이터가 사라졌을 때 당황하며 머리를 감싸 쥐는 운영자와, 침착하게 복구 스크립트를 실행하는 운영자의 차이는 평소의 준비성에서 갈려요.
- 데이터베이스는 반드시 전용 덤프 도구로 백업하세요.
- 설정 파일(.env, docker-compose.yml)도 반드시 함께 보호하세요.
- 백업 파일은 반드시 서버 외부 스토리지에 분리 보관하세요.
- 자동화 스크립트를 작성하고 크론(cron)으로 스케줄을 관리하세요.
- 가장 중요한 것은 정기적인 복구 테스트입니다.
지금 바로 여러분의 서버를 확인해 보세요. 백업 스크립트는 돌아가고 있나요? 그 파일이 정말로 복구 가능한 파일인가요? 백업은 성공했을지 몰라도, 복구에 실패한다면 그것은 백업이 아니에요.
오늘 바로 실천할 일: 지금 즉시 테스트용 컨테이너를 하나 띄우고, 방금 배운 방식으로 덤프를 뜬 뒤, 컨테이너를 삭제하고 다시 복구하는 과정을 딱 한 번만 해보세요. 그 한 번의 경험이 여러분의 서비스를 지켜줄 거예요.
복구는 실제로 한 번 해봐야 믿을 수 있습니다. 오늘 복구 테스트를 예약하세요.
관련하여 더 깊이 있는 인프라 운영 방법이 궁금하다면 아래 글을 참고해 보세요.
도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드