Docker 볼륨 백업과 마이그레이션 실전 가이드: 3가지 방법 완전 분석

작년 광군제 때 회사 서버를 Alibaba Cloud에서 Tencent Cloud로 옮겼습니다. 사장님이 Docker 안의 데이터베이스 데이터는 어떻게 할 거냐고 물었습니다. 반년 넘게 운영한 PostgreSQL 컨테이너에 수 GB의 사용자 데이터가 있었지만, 한 번도 백업한 적이 없었습니다.
그날 밤 저는 Docker 백업 방법을 미친 듯이 검색하며 수많은 튜토리얼을 읽었습니다. docker cp, tar 압축, docker-volume-backup 같은 도구까지… 읽을수록 더 헷갈렸습니다. 방법마다 맞는 말처럼 보였지만 무엇을 써야 할지 몰랐고, 운영 환경에서 시험해 볼 엄두도 나지 않았습니다. 백업 도중 데이터베이스가 데이터를 쓰다가 손상된 백업 파일이 만들어지는 상황이 가장 두려웠습니다.
그 후 몇 번 시행착오를 겪으면서 방법을 제대로 이해하게 됐습니다. 사실 Docker 데이터 백업은 그렇게 복잡하지 않습니다. 핵심은 각 방법이 어떤 상황에 적합한지 아는 것입니다. 이 글에서는 대표적인 백업 방법 3가지를 소개하고, 각각 언제 쓰는지, 어떻게 쓰는지, 무엇을 주의해야 하는지 설명하겠습니다. 다 읽고 나면 자신의 Docker 애플리케이션을 안정적으로 백업하는 방법을 알 수 있을 것입니다.
Docker 데이터 백업이 중요한 이유
Docker 데이터 저장 방식 간단히 이해하기
Docker를 처음 사용할 때는 데이터 저장을 크게 신경 쓰지 않는 사람이 많습니다. 컨테이너를 시작하면 바로 쓸 수 있고 데이터도 그대로 있으니 별문제가 없어 보입니다. 하지만 자주 놓치는 중요한 사실이 있습니다. 컨테이너 자체는 일시적입니다.
데이터를 컨테이너 내부에 직접 쓰면 다음에 컨테이너를 다시 만들거나 이미지를 업데이트할 때 데이터가 사라질 수 있습니다. 그래서 Docker는 데이터를 영구 보관하는 두 가지 방법을 제공합니다.
- Volume(볼륨): Docker가 직접 관리하는 스토리지 영역으로, 데이터는
/var/lib/docker/volumes/디렉터리에 저장됩니다. 공식 권장 방식이며 Docker가 권한과 수명 주기를 관리해 준다는 장점이 있습니다. - Bind Mount(바인드 마운트): 호스트의 특정 디렉터리를 컨테이너에 직접 마운트합니다. 예를 들어
/home/user/data를 컨테이너의/data에 마운트하면 데이터가 익숙한 위치에 저장되므로 백업할 때 바로cp하면 됩니다.
백업해야 할 데이터는 다음과 같습니다.
- 데이터베이스 파일(PostgreSQL, MySQL, MongoDB의 데이터 디렉터리)
- 사용자가 업로드한 파일(프로필 이미지, 문서, 사진)
- 설정 파일(대부분 다시 만들 수 있지만 민감한 설정은 백업하는 편이 안전함)
- 로그 파일(과거 로그를 분석해야 하는 경우)
흔히 발생하는 데이터 손실 상황
제가 직접 보거나 들은 데이터 손실 사고는 대체로 다음과 같습니다.
실수로 컨테이너를 삭제한 경우입니다. 가장 흔한 상황입니다. 테스트 컨테이너를 하나 지우려다가 docker rm -v를 실행해 볼륨까지 함께 삭제합니다. 문제의 -v 옵션은 연결된 익명 볼륨도 삭제합니다. 저도 처음에는 이 사실을 몰라 테스트 환경의 데이터베이스를 통째로 날린 적이 있습니다.
디스크 장애입니다. 서버를 2~3년 운영하다가 갑자기 디스크 SMART 경고가 떠서 서둘러 교체하게 됩니다. 데이터가 아직 읽히더라도 그때의 아찔함은 겪고 싶지 않습니다. 평소 백업이 있다면 디스크가 망가져도 새 디스크로 교체하고 복원해 수십 분 안에 서비스를 다시 띄울 수 있습니다.
서버 마이그레이션입니다. 앞에서 말한 상황입니다. 데이터센터나 클라우드 사업자를 바꾸든, VPS에서 Kubernetes로 서비스를 옮기든 데이터를 어떻게 이동할지가 큰 문제입니다. 백업이 없으면 scp 전송 중 네트워크가 끊기지 않기만을 기도할 수밖에 없습니다.
실제 사례도 있습니다. 작년에 지인의 스타트업에서 데이터베이스 컨테이너가 원인을 알 수 없이 중단됐습니다. 재시작한 뒤 볼륨의 데이터가 손상되어 PostgreSQL이 실행되지 않는다는 사실을 발견했습니다. 결국 찾은 가장 최근 백업은 두 달 전 것이었습니다. 두 달치 주문 데이터를 모두 잃어 회사에 수십만 위안의 손실이 발생했습니다.
겁을 주려는 것이 아닙니다. 정기 백업은 정말 중요합니다. 데이터가 사라지고 나면 아무리 뛰어난 기술도 되살릴 수 없습니다.
3가지 백업 방법 자세히 알아보기
방법 1: tar 명령어로 백업하기(⭐⭐⭐⭐⭐ 권장)
제가 가장 자주 쓰는 방법으로, 다양한 상황에 적합합니다. 핵심 원리는 간단합니다. 임시 컨테이너에 볼륨을 마운트한 다음 tar로 압축합니다.
백업 명령어:
docker run --rm \
-v postgres_data:/data:ro \
-v $(pwd):/backup \
ubuntu tar czf /backup/postgres-backup-20251217.tar.gz -C /data .
명령어를 하나씩 살펴보겠습니다.
--rm: 실행이 끝나면 컨테이너를 자동으로 삭제해 불필요한 컨테이너를 남기지 않습니다.-v postgres_data:/data:ro: 백업할 볼륨(postgres_data)을 컨테이너의 /data 디렉터리에 마운트합니다.:ro는 읽기 전용을 의미하며 실수를 방지합니다.-v $(pwd):/backup: 현재 디렉터리를 컨테이너의 /backup에 마운트하므로 백업 파일이 여기에 저장됩니다.tar czf: c는 아카이브 생성, z는 gzip 압축, f는 파일명 지정을 뜻합니다.-C /data .: /data 디렉터리로 이동해 모든 내용(.은 현재 디렉터리의 모든 파일)을 압축합니다.
복원 명령어:
docker run --rm \
-v postgres_data:/data \
-v $(pwd):/backup \
ubuntu tar xzf /backup/postgres-backup-20251217.tar.gz -C /data
여기서 x는 압축 해제를 의미하며 나머지 옵션은 백업할 때와 비슷합니다.
이 방법은 언제 사용하나요?
- 모든 볼륨 유형에 적합한 가장 범용적인 방법
- 압축해 공간을 절약해야 할 때(압축률은 30~50%에 이를 수 있음)
- 백업 파일을 다른 서버나 클라우드 스토리지로 옮겨야 할 때
주의사항:
처음 이 방법을 썼을 때 실행 중인 MySQL 컨테이너를 그대로 백업하는 실수를 했습니다. 백업 자체는 성공했지만 복원할 때 테이블이 손상됐다는 오류와 함께 데이터베이스가 시작되지 않았습니다. 나중에야 백업 중 데이터베이스가 데이터를 쓰면 일관되지 않은 상태가 담길 수 있다는 사실을 알았습니다.
가장 안전한 방법은 다음과 같습니다.
- 쓰기 작업 중지(컨테이너 중지 또는 테이블 잠금)
- 백업 실행
- 쓰기 작업 재개
서비스를 정말 중지할 수 없다면 최소한 데이터베이스에서 journal 또는 WAL 로그를 활성화해야 합니다. 그러면 백업 중 쓰기가 발생해도 복원 후 데이터베이스가 자체적으로 복구할 수 있습니다.
실전 사례: PostgreSQL 데이터 백업
# 1. PostgreSQL 컨테이너 중지(가능한 경우)
docker stop my-postgres
# 2. 볼륨 백업
docker run --rm \
-v postgres_data:/data:ro \
-v /backup:/backup \
ubuntu tar czf /backup/pg-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
# 3. 백업 파일 검증
ls -lh /backup/pg-*.tar.gz
# 4. 컨테이너 재시작
docker start my-postgres
파일명에는 타임스탬프를 넣는 편입니다. 그러면 언제 만든 백업인지 한눈에 알 수 있습니다.
방법 2: docker cp 명령어 사용하기(⭐⭐⭐)
이 방법은 더 직관적입니다. 압축하지 않고 파일을 바로 복사합니다. 설정 파일 몇 개나 작은 디렉터리를 빠르게 백업할 때 적합합니다.
백업 단계:
# 1. 볼륨을 연결한 임시 컨테이너 생성
docker create -v nginx_config:/data --name temp_backup busybox
# 2. 데이터를 호스트로 복사
docker cp temp_backup:/data ./nginx-config-backup
# 3. 임시 컨테이너 정리
docker rm temp_backup
복원 단계:
# 새 컨테이너에 복원한다고 가정
docker cp ./nginx-config-backup/. my-nginx:/etc/nginx/
이 방법은 언제 사용하나요?
- 설정 파일 몇 개만 백업할 때
- 파일이 작을 때(수십 MB 이내)
- 압축을 풀지 않고 백업 내용을 빠르게 확인하고 싶을 때
단점:
- 압축을 지원하지 않아 큰 파일은 공간을 많이 차지함
- tar보다 전송 속도가 다소 느림
- 모든 권한과 특수 속성을 완벽하게 보존하지 못함
실전 사례: Nginx 설정 백업
# 임시 컨테이너 생성
docker create -v nginx_config:/config --name nginx_temp busybox
# 설정 파일 복사
docker cp nginx_temp:/config/nginx.conf ./backup/
# 전체 디렉터리도 복사 가능
docker cp nginx_temp:/config/. ./backup/nginx-config/
# 정리
docker rm nginx_temp
저는 보통 설정 파일을 백업할 때 이 방법을 사용합니다. 예를 들어 Nginx 설정을 갑자기 바꿔야 한다면 수정 전에 docker cp로 한 부를 복사해 둡니다. 설정이 망가져도 빠르게 복원할 수 있습니다.
방법 3: docker-volume-backup 도구 사용하기(⭐⭐⭐⭐ 자동화에 가장 적합)
앞의 두 방법은 수동 작업이라 임시 백업에 적합합니다. 하지만 운영 환경에서는 당연히 정기 백업을 자동화하고 싶을 것입니다. 이때는 도구를 사용해야 합니다.
저는 현재 offen/docker-volume-backup을 사용합니다. 2025년에 비교적 인기 있는 오픈 소스 솔루션으로 다음 기능을 제공합니다.
- 정기 자동 백업(cron 표현식으로 설정)
- 백업 전에 컨테이너를 자동으로 중지해 데이터 일관성 보장
- 다양한 스토리지 백엔드 지원(S3, Google Drive, SSH, WebDAV)
- 오래된 백업 자동 정리
Docker Compose 설정 예시:
version: '3.8'
services:
# 데이터베이스 서비스
postgres:
image: postgres:15
volumes:
- db_data:/var/lib/postgresql/data
labels:
# 백업 중 이 컨테이너를 중지하도록 표시
- "docker-volume-backup.stop-during-backup=true"
# 백업 서비스
backup:
image: offen/docker-volume-backup:latest
environment:
# 매일 새벽 2시에 백업
BACKUP_CRON_EXPRESSION: "0 2 * * *"
# 백업 파일 이름
BACKUP_FILENAME: "db-backup-%Y%m%d-%H%M%S.tar.gz"
# 최근 7일간의 백업 보관
BACKUP_RETENTION_DAYS: "7"
volumes:
# 백업할 볼륨(읽기 전용)
- db_data:/backup/db_data:ro
# 백업 파일 저장 위치
- ./backups:/archive
# 컨테이너를 중지하려면 Docker socket 마운트 필요
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
db_data:
작업 흐름:
- 매일 새벽 2시에 백업 컨테이너 시작
postgres컨테이너에stop-during-backup레이블이 있음을 감지하고 자동 중지- tar로
db_data볼륨 압축 - 백업 파일을
./backups디렉터리에 저장 postgres컨테이너 자동 시작- 7일이 지난 오래된 백업 삭제
이 방법은 언제 사용하나요?
- 정기 자동 백업이 필요한 운영 환경
- 백업을 클라우드 스토리지(S3, GCS 등)로 전송하고 싶을 때
- 여러 컨테이너의 백업을 관리할 때
주의사항:
처음 설정할 때는 권한 문제에 주의해야 합니다. 백업 컨테이너가 다른 컨테이너를 중지하려면 /var/run/docker.sock을 읽을 수 있어야 합니다.
또한 이 도구는 실제로 서비스를 몇 초에서 몇십 초간 중지합니다. 소요 시간은 데이터 양에 따라 달라집니다. 서비스를 중지할 수 없다면 stop-during-backup 레이블을 사용하지 마세요. 다만 이 경우 일관되지 않은 상태가 백업될 위험을 감수해야 합니다.
실전 사례: MongoDB 자동 백업
version: '3.8'
services:
mongodb:
image: mongo:7
volumes:
- mongo_data:/data/db
labels:
- "docker-volume-backup.stop-during-backup=true"
backup:
image: offen/docker-volume-backup:latest
environment:
BACKUP_CRON_EXPRESSION: "0 3 * * *"
BACKUP_FILENAME: "mongo-%Y%m%d.tar.gz"
BACKUP_RETENTION_DAYS: "14"
# AWS S3에 백업
AWS_S3_BUCKET_NAME: "my-backups"
AWS_ACCESS_KEY_ID: "${AWS_KEY}"
AWS_SECRET_ACCESS_KEY: "${AWS_SECRET}"
volumes:
- mongo_data:/backup/mongo_data:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
mongo_data:
이 설정은 매일 새벽 3시에 MongoDB를 자동으로 백업하고 백업 파일을 S3에 업로드하며 로컬에는 보관하지 않습니다. 저는 이 설정을 반년 넘게 사용했고 매우 안정적이었습니다.
데이터 마이그레이션 전체 절차
서버 마이그레이션 실전 단계
백업 방법을 살펴봤으니 이제 실제로 서버를 옮기는 전체 절차를 알아보겠습니다. 저는 작년에 Alibaba Cloud에서 Tencent Cloud로 마이그레이션했고, 전체 과정은 대략 다음과 같았습니다.
1. 준비 단계(절대 건너뛰지 마세요)
먼저 현재 환경을 정확히 파악합니다.
# 모든 컨테이너 나열
docker ps -a
# 모든 볼륨 나열
docker volume ls
# 각 컨테이너의 설정 내보내기(매우 중요!)
docker inspect my-postgres > postgres-config.json
docker inspect my-nginx > nginx-config.json
# docker-compose.yml과 .env 파일 보관
cp docker-compose.yml docker-compose.backup.yml
cp .env .env.backup
이 설정 파일은 반드시 잘 백업해야 합니다. 처음 마이그레이션했을 때 환경 변수를 저장하는 것을 잊어 새 서버의 데이터베이스 비밀번호가 맞지 않았고, 해결하는 데 오랜 시간이 걸렸습니다.
2. 백업 단계
모든 서비스를 중지하고 백업을 시작합니다.
# 모든 컨테이너 중지
docker-compose down
# 각 볼륨 백업
docker run --rm \
-v postgres_data:/data:ro \
-v $(pwd)/backups:/backup \
ubuntu tar czf /backup/postgres_data.tar.gz -C /data .
docker run --rm \
-v nginx_config:/data:ro \
-v $(pwd)/backups:/backup \
ubuntu tar czf /backup/nginx_config.tar.gz -C /data .
# 백업 파일 검증
ls -lh backups/
md5sum backups/*.tar.gz > backups/checksums.txt
md5sum은 매우 중요합니다. 파일 전송 중 네트워크가 불안정해 파일이 손상되더라도 이를 발견할 수 있습니다.
3. 마이그레이션 단계
백업 파일을 새 서버로 전송합니다.
# 중단된 전송을 이어 갈 수 있는 rsync를 주로 사용
rsync -avP --partial backups/ user@new-server:/tmp/backups/
# 또는 scp 사용
scp -r backups/ user@new-server:/tmp/backups/
파일이 매우 크고(수십 GB 정도) 네트워크도 불안정하다면 클라우드 오브젝트 스토리지를 중간 경유지로 사용하는 것이 좋습니다. 먼저 S3나 OSS에 업로드한 뒤 새 서버에서 내려받으면 더 빠르고 안정적입니다.
새 서버에서 복원하기:
# 1. 볼륨 생성
docker volume create postgres_data
docker volume create nginx_config
# 2. 데이터 복원
docker run --rm \
-v postgres_data:/data \
-v /tmp/backups:/backup \
ubuntu tar xzf /backup/postgres_data.tar.gz -C /data
docker run --rm \
-v nginx_config:/data \
-v /tmp/backups:/backup \
ubuntu tar xzf /backup/nginx_config.tar.gz -C /data
# 3. 복원 데이터 검증
docker run --rm -v postgres_data:/data ubuntu ls -lh /data
# 4. 서비스 시작
docker-compose up -d
4. 검증 단계
서비스가 시작됐다고 바로 트래픽을 전환하지 말고 먼저 검증합니다.
# 컨테이너 상태 확인
docker ps
# 로그를 확인해 오류가 없는지 점검
docker-compose logs -f
# 데이터베이스 연결 테스트
docker exec -it my-postgres psql -U postgres -c "SELECT COUNT(*) FROM users;"
# 새 서버와 기존 서버의 데이터 비교
# (저는 보통 핵심 테이블의 레코드 수를 비교하는 스크립트를 작성합니다.)
모든 것이 정상일 때 DNS나 로드 밸런서 설정을 변경해 트래픽을 새 서버로 전환합니다.
제가 겪은 실수:
작년 마이그레이션 때 50GB에 달하는 볼륨이 하나 있었고, docker run tar 방식으로 압축을 푸는 데 거의 한 시간이 걸렸습니다. 나중에 알고 보니 docker volume create로 볼륨을 먼저 만든 뒤 호스트의 /var/lib/docker/volumes/volume_name/_data에 직접 압축을 풀면 훨씬 빨랐습니다. 다만 이 방식은 권한 문제에 주의해야 합니다.
데이터베이스 백업 시 특별히 주의할 점
데이터베이스 백업은 함정이 많아서 따로 설명하겠습니다.
파일 수준 백업이 충분히 신뢰할 수 없는 이유는 무엇인가요?
데이터베이스가 실행되는 동안에는 데이터가 계속 기록됩니다. MySQL의 InnoDB 엔진에는 redo log와 undo log가 있고 PostgreSQL에는 WAL 로그가 있습니다. 모두 트랜잭션 일관성을 보장하기 위한 장치입니다. 데이터 파일을 tar로 직접 압축하면 압축 도중 데이터베이스가 트랜잭션을 쓰는 순간이 생길 수 있고, 백업은 일관되지 않은 상태가 됩니다.
가장 심각한 사례도 봤습니다. 누군가 MySQL을 백업할 때 마침 데이터베이스가 대규모 트랜잭션, 즉 수백만 건의 데이터 일괄 삽입을 수행하고 있었습니다. 백업 파일은 정상처럼 보였지만 복원 후에는 InnoDB 테이블스페이스가 손상됐다는 오류와 함께 MySQL이 전혀 시작되지 않았습니다.
올바른 방법: 애플리케이션 수준 백업 사용하기
PostgreSQL:
# 단일 데이터베이스 백업
docker exec my-postgres pg_dump -U postgres mydb > mydb-backup.sql
# 모든 데이터베이스 백업
docker exec my-postgres pg_dumpall -U postgres > all-dbs-backup.sql
# 복원
docker exec -i my-postgres psql -U postgres mydb < mydb-backup.sql
MySQL:
# 백업
docker exec my-mysql mysqldump -u root -p mydb > mydb-backup.sql
# 복원
docker exec -i my-mysql mysql -u root -p mydb < mydb-backup.sql
MongoDB:
# 백업
docker exec my-mongo mongodump --out=/backup
docker cp my-mongo:/backup ./mongo-backup
# 복원
docker cp ./mongo-backup my-mongo:/backup
docker exec my-mongo mongorestore /backup
이중 보호 전략:
저는 현재 애플리케이션 수준 백업 + 볼륨 백업을 함께 사용합니다.
- 애플리케이션 수준 백업(pg_dump 등): 데이터 일관성이 보장되므로 주된 복원 수단으로 사용
- 볼륨 백업(tar 압축): 재해 복구용 보조 수단으로 사용. 애플리케이션 수준 백업이 실패하거나 손상되더라도 파일 수준 백업을 시도할 수 있음
공간을 조금 더 차지하지만 훨씬 안전합니다. 앞서 말한 지인의 회사가 데이터를 잃은 이유도 볼륨 백업만 있었고, 복원할 때 그 백업이 손상된 사실을 발견했기 때문입니다. 애플리케이션 수준 백업은 아예 하지 않았습니다.
모범 사례와 실수 방지 가이드
백업 전략 설계
백업 방법이 있어도 합리적인 백업 전략이 필요합니다. 그렇지 않으면 너무 자주 백업해 리소스를 낭비하거나 너무 드물게 백업해 데이터를 잃게 됩니다.
3-2-1 원칙(업계에서 널리 사용하는 백업의 황금 원칙):
- 복사본 3개: 원본 데이터 + 백업 2개
- 저장 매체 2종: 로컬 디스크 + 클라우드 스토리지 또는 서로 다른 디스크 2개
- 외부 보관 1개: 화재나 지진 등에 대비해 최소 1개는 다른 지역에 보관
복잡해 보이지만 구현은 어렵지 않습니다. 저는 다음과 같이 운영합니다.
- 로컬 서버에 최근 7일의 일일 백업 보관(첫 번째 백업)
- NAS에 최근 30일의 백업 보관(두 번째 백업, 다른 저장 매체)
- S3에 최근 3개월의 월간 백업 보관(세 번째 백업, 외부 보관)
권장 백업 주기:
| 데이터 중요도 | 백업 주기 | 보관 정책 |
|---|---|---|
| 핵심 데이터베이스 | 매시간 | 최근 24시간은 시간당 1개, 최근 7일은 일일 1개 |
| 일반 애플리케이션 데이터 | 매일 | 최근 7일은 일일 1개, 최근 4주는 주간 1개 |
| 설정 파일 | 변경할 때 | 변경 전에 수동 백업, 최근 10개 버전 보관 |
| 로그 파일 | 매주 | 최근 4주는 주간 1개 |
백업 파일 이름 규칙:
이름을 가볍게 보면 안 됩니다. 이름이 뒤죽박죽이면 복원할 때 혼란에 빠집니다. 제가 사용하는 형식은 다음과 같습니다.
<서비스명>-<데이터 유형>-<YYYYMMDD>-<HHMMSS>.tar.gz
예시:
myapp-postgres-20251217-020000.tar.gz
myapp-nginx-config-20251217-020000.tar.gz
myapp-uploads-20251217-020000.tar.gz
이렇게 하면 정렬할 때 자연스럽게 시간순으로 나열되고 언제 만든 백업인지 한눈에 알 수 있습니다.
자주 발생하는 문제와 해결 방법
문제 1: 백업할 때 volume is in use 오류가 표시됨
볼륨은 여러 컨테이너에 동시에 마운트할 수 있으므로 보통 이 오류는 실제로 발생하지 않습니다. 그래도 이 오류가 나타난다면 다음 원인일 수 있습니다.
- 컨테이너에 파일 잠금이 있음
- NFS 또는 다른 네트워크 스토리지 마운트 문제
해결 방법:
# 이 볼륨을 사용하는 컨테이너 확인
docker ps --filter volume=my_volume
# 가능하다면 해당 컨테이너 중지
docker stop container_name
# 또는 --volumes-from 매개변수 사용
docker run --rm --volumes-from=my_container -v $(pwd):/backup ubuntu tar czf /backup/data.tar.gz -C /data .
문제 2: 복원 후 파일 권한이 올바르지 않음
저도 겪었던 문제입니다. tar는 기본적으로 권한 정보를 보존하지만 서로 다른 시스템 사이에서 마이그레이션하면(예: Ubuntu에서 CentOS로 이동) UID/GID가 일치하지 않을 수 있습니다.
증상은 컨테이너가 일부 파일을 읽거나 쓸 권한이 없다는 오류와 함께 시작되지 않는 것입니다.
해결 방법:
# 복원할 때 owner 지정
docker run --rm -v my_volume:/data -v $(pwd):/backup ubuntu sh -c "tar xzf /backup/data.tar.gz -C /data && chown -R 999:999 /data"
# 999:999는 PostgreSQL 컨테이너 내부 postgres 사용자의 UID
# 이미지마다 UID가 다르므로 문서나 docker inspect로 확인해야 함
문제 3: 백업 파일이 너무 커서 전송하기 어려움
예전에 50GB짜리 MySQL 데이터베이스를 백업했는데 gzip으로 압축해도 30GB였습니다. 공용 네트워크로 전송하니 매우 느렸고 자주 중단됐습니다.
해결 방법:
-
더 높은 압축률 사용: xz 형식은 gzip보다 압축률이 20~30% 높지만 속도가 더 느립니다.
tar cJf backup.tar.xz /data # J는 xz 압축을 의미 -
분할 압축: 파일 크기 제한이 있는 곳으로 전송할 때 적합합니다.
tar czf - /data | split -b 1G - backup.tar.gz. # 복원할 때: cat backup.tar.gz.* | tar xzf - -
증분 백업: 변경된 파일만 백업합니다(rsync나 전문 백업 소프트웨어 같은 도구 필요).
문제 4: 복원할 때 백업 파일이 손상된 것을 발견함
가장 곤란한 상황입니다. 백업 당시에는 문제를 발견하지 못하고, 실제로 필요할 때 파일이 손상됐음을 알게 됩니다.
예방 방법:
# 백업 직후 검증
md5sum backup.tar.gz > backup.tar.gz.md5
# 새 서버로 전송한 뒤 다시 검증
md5sum -c backup.tar.gz.md5
# 정기 복원 테스트(가장 중요!)
# 매달 테스트 환경에서 백업을 실제로 복원해 사용할 수 있는지 검증
저는 백업이 끝날 때마다 앞부분의 파일 몇 개라도 압축을 풀어 봅니다. 최소한 백업 파일 자체가 온전한지는 확인할 수 있습니다.
자동화와 모니터링
수동 백업은 안정적이지만 사람은 잊기 마련입니다. 운영 환경에서는 반드시 자동화해야 합니다.
crontab으로 백업 스크립트 정기 실행하기:
# 백업 스크립트 /opt/scripts/backup-docker-volumes.sh 생성
#!/bin/bash
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_DIR=/backup
# PostgreSQL 백업
docker run --rm \
-v postgres_data:/data:ro \
-v $BACKUP_DIR:/backup \
ubuntu tar czf /backup/postgres-$DATE.tar.gz -C /data .
# Nginx 설정 백업
docker run --rm \
-v nginx_config:/data:ro \
-v $BACKUP_DIR:/backup \
ubuntu tar czf /backup/nginx-$DATE.tar.gz -C /data .
# 7일이 지난 오래된 백업 정리
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
# 알림 전송(선택 사항)
echo "Backup completed: $DATE" | mail -s "Docker Backup Report" [email protected]
# crontab에 추가
crontab -e
# 매일 새벽 2시에 실행
0 2 * * * /opt/scripts/backup-docker-volumes.sh >> /var/log/docker-backup.log 2>&1
모니터링과 알림:
자동화만으로는 충분하지 않습니다. 백업 성공 여부도 알아야 합니다. 저는 다음과 같이 관리합니다.
- 로그 기록: 백업할 때마다 시간, 파일 크기, MD5를 로그에 기록
- 모니터링 스크립트: 매일 새 백업 파일이 생성됐는지 확인하고 없으면 알림
- 비정상 파일 크기 감지: 백업 파일이 갑자기 매우 커지거나 작아지면(평균보다 50% 이상 차이) 문제가 있을 수 있음
간단한 모니터링 스크립트:
#!/bin/bash
BACKUP_DIR=/backup
EXPECTED_SIZE=100000000 # 100MB, 실제 상황에 맞게 조정
LATEST_BACKUP=$(ls -t $BACKUP_DIR/postgres-*.tar.gz | head -1)
if [ -z "$LATEST_BACKUP" ]; then
echo "ERROR: No backup file found!"
exit 1
fi
# 백업 파일이 오늘 생성됐는지 확인
BACKUP_DATE=$(stat -c %Y "$LATEST_BACKUP")
TODAY=$(date +%s)
AGE=$((TODAY - BACKUP_DATE))
if [ $AGE -gt 86400 ]; then
echo "ERROR: Latest backup is older than 24 hours!"
exit 1
fi
# 파일 크기 확인
SIZE=$(stat -c %s "$LATEST_BACKUP")
if [ $SIZE -lt $(($EXPECTED_SIZE / 2)) ]; then
echo "WARNING: Backup file is too small: $SIZE bytes"
exit 1
fi
echo "Backup check passed: $LATEST_BACKUP ($SIZE bytes)"
이러한 모니터링 스크립트는 Prometheus나 Zabbix 같은 모니터링 시스템에 통합하거나 이메일 또는 WeCom 알림으로 보낼 수 있습니다.
결론
지금까지의 내용을 처음 질문으로 정리해 보겠습니다. Docker 데이터는 어떻게 백업해야 할까요?
정답은 간단합니다. 모든 상황에 맞는 만능 방법은 없으며, 자신의 상황에 맞는 방법을 선택하는 것이 중요합니다.
- 임시 백업과 빠른 마이그레이션: 범용적이고 안정적인 tar 방법 사용
- 설정 파일과 작은 파일: 간단하고 직관적인 docker cp로 충분
- 자동화가 필요한 운영 환경: 편리한 docker-volume-backup 사용
그리고 가장 중요한 점은 정기적으로 백업하고 정기적으로 복원을 테스트하는 것입니다. 실제 복원이 필요해진 뒤에야 백업 파일이 손상됐거나 아예 복원할 수 없다는 사실을 발견해서는 안 됩니다. 저는 매달 테스트 환경을 마련해 최신 백업을 실제로 한 번 복원하고 절차에 문제가 없는지 검증합니다.
마지막으로 한 가지 권하고 싶습니다. 오늘 바로 Docker 애플리케이션의 첫 백업을 해보세요. 복잡할 필요 없이 가장 간단한 tar 방법으로 한 번 백업해 보면 됩니다. 백업 파일이 디스크에 있으면 훨씬 안심할 수 있습니다.
백업 과정에서 문제가 생겼거나 더 좋은 방법을 알고 있다면 댓글로 이야기해 주세요. 함께 경험을 나누면 시행착오를 줄일 수 있습니다.
Docker 볼륨 백업과 마이그레이션 전체 절차
tar 압축, docker cp 명령어, 자동화 도구의 3가지 방법과 데이터베이스 백업 주의사항, 서버 마이그레이션 전체 절차를 자세히 설명합니다.
⏱️ Estimated time: 1 hr
- 1
Step 1: 문제 배경과 3가지 백업 방법 이해하기
문제 배경:
• 반년 넘게 운영한 PostgreSQL 컨테이너에 수 GB의 사용자 데이터가 있음
• 한 번도 백업하지 않았다면 서버 마이그레이션 시 데이터를 어떻게 해야 할까?
• 신뢰할 수 있는 백업 방안이 필요함
3가지 백업 방법:
1. tar 압축(권장)
• docker run --rm -v volume-name:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz /data
• 일회성 백업에 적합하고 간단하며 안정적이고, 압축으로 공간을 절약할 수 있음
2. docker cp 명령어
• docker cp container-name:/data ./backup
• 작은 파일 백업에 적합하고 별도 도구 없이 파일을 직접 복사함
3. 자동화 도구
• docker-volume-backup, velero 등
• 정기 백업에 적합하고 자동 스케줄링과 다양한 스토리지 백엔드를 지원함 - 2
Step 2: 데이터베이스 백업 주의사항과 서버 마이그레이션
데이터베이스 백업 주의사항:
• 백업 전에 데이터베이스를 중지하거나 pg_dump 같은 도구 사용
• 백업 중 데이터베이스 쓰기로 인한 손상 방지
• --volumes-from 매개변수로 실행 중인 컨테이너 데이터 백업
MySQL 백업:
• mysqldump로 데이터 내보내기
• 또는 컨테이너를 중지한 후 데이터 디렉터리 백업
PostgreSQL 백업:
• pg_dump로 데이터 내보내기
• 또는 컨테이너를 중지한 후 데이터 디렉터리 백업
Redis 백업:
• redis-cli --rdb로 RDB 파일 내보내기
• 또는 컨테이너를 중지한 후 데이터 디렉터리 백업
서버 마이그레이션 전체 절차:
1. 볼륨 백업(tar 또는 docker cp 사용)
2. 백업 파일을 새 서버로 전송(scp, rsync 등 사용)
3. 새 서버에서 볼륨 복원:
docker run --rm -v volume-name:/data -v $(pwd):/backup alpine tar xzf /backup/backup.tar.gz -C /data
4. 컨테이너를 시작하고 데이터 검증
검증 단계:
• 데이터 파일 존재 여부 확인
• 파일 권한이 올바른지 확인
• 애플리케이션이 데이터에 정상 접근하는지 테스트 - 3
Step 3: 모범 사례와 자동화
모범 사례:
• 볼륨을 정기적으로 백업
• 자동화 도구 사용
• 백업 복원 절차 테스트
• 백업 전에 데이터베이스를 중지하거나 데이터베이스 백업 도구 사용
• 백업 파일 무결성 검증
그리고 가장 중요한 점:
• 정기적으로 백업하고 정기적으로 복원 테스트
• 실제 복원이 필요해진 뒤에야 백업 파일이 손상됐거나 아예 복원할 수 없다는 사실을 발견하지 말 것
• 매달 테스트 환경을 마련해 최신 백업을 실제로 한 번 복원하고 절차에 문제가 없는지 검증
오늘 바로 Docker 애플리케이션의 첫 백업을 해보세요. 복잡할 필요 없이 가장 간단한 tar 방법으로 한 번 백업해 보세요. 백업 파일이 디스크에 있으면 훨씬 안심할 수 있습니다.
FAQ
Docker 볼륨을 백업하는 방법에는 무엇이 있나요?
1) tar 압축: docker run --rm -v volume-name:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz /data
2) docker cp 명령어: docker cp container-name:/data ./backup
3) 자동화 도구: docker-volume-backup, velero 등
방법 비교:
• tar 압축: 일회성 백업에 적합하고 간단하며 안정적이고, 압축으로 공간을 절약할 수 있음
• docker cp 명령어: 작은 파일 백업에 적합하고 별도 도구 없이 파일을 직접 복사함
• 자동화 도구: 정기 백업에 적합하고 자동 스케줄링과 다양한 스토리지 백엔드를 지원함
데이터베이스 백업 시 무엇을 주의해야 하나요?
• 백업 전에 데이터베이스를 중지하거나 pg_dump 같은 도구 사용
• 백업 중 데이터베이스 쓰기로 인한 손상 방지
• --volumes-from 매개변수로 실행 중인 컨테이너 데이터 백업
데이터베이스별 백업 방법:
• MySQL 백업: mysqldump로 데이터를 내보내거나 컨테이너를 중지한 후 데이터 디렉터리 백업
• PostgreSQL 백업: pg_dump로 데이터를 내보내거나 컨테이너를 중지한 후 데이터 디렉터리 백업
• Redis 백업: redis-cli --rdb로 RDB 파일을 내보내거나 컨테이너를 중지한 후 데이터 디렉터리 백업
Docker 볼륨을 새 서버로 어떻게 마이그레이션하나요?
1) 볼륨 백업(tar 또는 docker cp 사용)
2) 백업 파일을 새 서버로 전송(scp, rsync 등 사용)
3) 새 서버에서 볼륨 복원:
docker run --rm -v volume-name:/data -v $(pwd):/backup alpine tar xzf /backup/backup.tar.gz -C /data
4) 컨테이너를 시작하고 데이터 검증
검증 단계:
• 데이터 파일 존재 여부 확인
• 파일 권한이 올바른지 확인
• 애플리케이션이 데이터에 정상 접근하는지 테스트
Docker 데이터 백업의 모범 사례는 무엇인가요?
• 볼륨을 정기적으로 백업
• 자동화 도구 사용
• 백업 복원 절차 테스트
• 백업 전에 데이터베이스를 중지하거나 데이터베이스 백업 도구 사용
• 백업 파일 무결성 검증
그리고 가장 중요한 점:
• 정기적으로 백업하고 정기적으로 복원 테스트
• 실제 복원이 필요해진 뒤에야 백업 파일이 손상됐거나 아예 복원할 수 없다는 사실을 발견하지 말 것
• 매달 테스트 환경을 마련해 최신 백업을 실제로 한 번 복원하고 절차에 문제가 없는지 검증
오늘 바로 Docker 애플리케이션의 첫 백업을 해보세요. 복잡할 필요 없이 가장 간단한 tar 방법으로 한 번 백업해 보세요. 백업 파일이 디스크에 있으면 훨씬 안심할 수 있습니다.
4분 읽기 · 게시일: 2025년 12월 17일 · 수정일: 2026년 9월 4일
Docker 실전 가이드
검색으로 들어왔다면 같은 시리즈의 이전 글이나 다음 글로 이동하는 것이 가장 빠릅니다.
이전
Docker 볼륨 실전 가이드: 5가지 예제로 컨테이너 데이터 유실 완벽 해결
5가지 실전 사례를 통해 Docker Volume의 기본 개념부터 MySQL·Redis 영속화까지 단계별로 익혀, 컨테이너를 삭제해도 데이터가 사라지지 않도록 만드는 방법을 설명합니다. Docker 초보자와 개발자에게 적합합니다.
33편 중 13편
다음
Docker 마운트 방식 비교: Volume vs Bind Mount 선택 가이드(성능 테스트 포함)
Docker의 세 가지 마운트 방식을 자세히 비교하고, Mac에서 npm install이 3배 느려지는 성능 문제를 해결하며, 의사결정 트리와 실제 사례를 통해 Volume, Bind Mount, tmpfs를 빠르게 선택하는 방법을 소개합니다.
33편 중 15편



댓글
GitHub로 로그인하여 댓글을 남기세요