Docker GitLab 백업 자동화 — gitlab-backup + NAS 이중화
GitLab도 이중화 백업을 하자는 지시가 내려옴. 소스코드는 이미 NAS로 백업하고 있었으니, 이제 GitLab 서버 자체도 백업 대상이 된 거임.
찾아보니 GitLab에 백업 명령어가 내장돼 있음. gitlab-backup create. 도커 내부에서 이걸 실행하면 저장소·DB가 통째로 tar로 떨어짐. 그래서 흐름을 이렇게 잡음.
- 도커 내부에서
gitlab-backup create로 백업 생성 - 생성된 tar 파일을
docker cp로 호스트로 꺼냄 - 꺼낸 파일을 NAS로 보냄 (기존 백업 체계에 합류)
백업 구조
기존 이중화에 GitLab이 끼면서 전체 그림이 이렇게 됨.
[A] 홈페이지 서버 ──── rsync ────> [B] NAS (기존 이중화)
│ ▲
rsync │
│ │ gitlab-backup tar
▼ │ (이번에 추가)
[C] GitLab 서버 ────────────────────┘
보면서 홈페이지 서버 소스코드를 NAS 로 저장 안해도 되지 않을까? 생각은 들었음.
백업 스크립트
백업 생성 → 꺼내기 → 컨테이너 내부 정리 → 데이터 디렉터리 복사 → 오래된 백업 삭제까지 한 번에 도는 스크립트. 경로는 환경에 맞게 바꾸면 됨.
#!/bin/bash
# 설정
CONTAINER_NAME="gitlab" # GitLab 컨테이너 이름
BACKUP_DIR="/backup/gitlab" # 호스트의 백업 저장 위치
HOST_DATA_DIR="/data/gitlab" # 호스트에서 백업할 GitLab 데이터 경로 (volume 마운트 경로)
RETENTION_DAYS=10 # 보관 기간 (일)
# 함수: 로그 출력
log() {
echo "[$(date)] $1"
}
# 1. 백업 생성
log "백업 생성 중..."
docker exec -t "$CONTAINER_NAME" gitlab-backup create
# 2. 컨테이너에서 최신 백업 파일 찾기
log "최신 백업 파일 검색 중..."
LATEST_BACKUP=$(docker exec -t "$CONTAINER_NAME" ls /var/opt/gitlab/backups | grep '.tar' | tail -n 1 | tr -d '\r' | tr -d '\n')
if [ -z "$LATEST_BACKUP" ]; then
log "최신 백업 파일을 찾지 못했습니다. 백업 파일이 생성되었는지 확인하세요."
exit 1
fi
log "최신 백업 파일: $LATEST_BACKUP"
# 3. 최신 백업 파일 복사
log "최신 백업 파일 복사 중..."
docker cp "$CONTAINER_NAME:/var/opt/gitlab/backups/$LATEST_BACKUP" "$BACKUP_DIR"
if [ $? -eq 0 ]; then
log "백업 파일 복사 완료: $BACKUP_DIR/$LATEST_BACKUP"
# 4. 컨테이너 내부 백업 파일 삭제
log "컨테이너 내부 백업 파일 삭제 중..."
docker exec -t "$CONTAINER_NAME" rm -f "/var/opt/gitlab/backups/$LATEST_BACKUP"
if [ $? -eq 0 ]; then
log "컨테이너 내부 백업 파일 삭제 완료: $LATEST_BACKUP"
else
log "컨테이너 내부 백업 파일 삭제 실패! 수동으로 확인하세요."
fi
else
log "백업 파일 복사 실패! 파일을 삭제하지 않습니다."
exit 1
fi
# 5. 호스트 데이터 디렉터리 복사
log "GitLab 데이터 디렉터리 복사 중..."
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
HOST_BACKUP_DIR="$BACKUP_DIR/gitlab_data_$TIMESTAMP"
cp -r "$HOST_DATA_DIR" "$HOST_BACKUP_DIR"
if [ $? -eq 0 ]; then
log "GitLab 데이터 디렉터리 복사 완료: $HOST_BACKUP_DIR"
else
log "GitLab 데이터 디렉터리 복사 실패! 수동으로 확인하세요."
exit 1
fi
# 6. 오래된 백업 파일 삭제
log "$RETENTION_DAYS일 이상 지난 백업 파일 삭제 중..."
find "$BACKUP_DIR" -type f -name '*.tar' -mtime +$RETENTION_DAYS -exec rm -f {} \;
find "$BACKUP_DIR" -type d -name 'gitlab_data_*' -mtime +$RETENTION_DAYS -exec rm -rf {} \;
if [ $? -eq 0 ]; then
log "$RETENTION_DAYS일 이상 지난 백업 파일 삭제 완료."
else
log "오래된 백업 파일 삭제 실패! 수동으로 확인하세요."
fi
# 7. 완료 메시지 출력
log "자동화 작업 완료."
포인트:
gitlab-backup create— 저장소·DB를 tar 하나로 묶어줌. 도커면docker exec로 실행.docker cp로 꺼내고 컨테이너 내부 파일은 삭제 — 안 지우면 컨테이너 안에 백업이 쌓여서 디스크 참사남. 복사 실패 시엔 안 지우게 해둠.- 데이터 디렉터리도 별도 복사 —
gitlab-backup은 설정 파일(gitlab.rb, 시크릿)까지는 안 챙겨줘서 volume 마운트된 데이터 경로를 통째로 한 번 더 뜸. - 보관 기간 10일 —
find -mtime으로 오래된 tar와 데이터 복사본을 정리. 안 하면 디스크가 남아나질 않음.
이렇게 호스트에 모인 백업 파일을 기존 NAS 백업 경로에 태워서 이중화 완성.
테스트
docker compose에서 volume 경로만 스크립트의 HOST_DATA_DIR와 맞게 잡아주면 잘 동작함. 크론에 걸어서 매일 돌리면 끝.
# 매일 새벽 3시 백업
0 3 * * * /root/scripts/gitlab-backup.sh >> /var/log/gitlab-backup.log 2>&1
정리
- GitLab 백업은 내장 명령어
gitlab-backup create하나로 됨. 도커여도docker exec로 해결. - 백업 tar는 밖으로 꺼내고 컨테이너 안은 비울 것. 설정/시크릿은 백업에 안 들어가니 데이터 디렉터리도 따로 뜰 것.
- 보관 기간 정해서 오래된 백업 자동 삭제까지 넣어야 운영이 됨.