본문 바로가기

Docker-compose - .sh 파일과 DB 백업 본문

개발/알쓸코잡

Docker-compose - .sh 파일과 DB 백업

자전하는명왕성 2025. 5. 9. 23:14
반응형

이번 포스팅은 Docker-compose 를 사용하며, 데이터베이스를 백업하는 방식에 대해 다룬다.

 

먼저, 해당 포스팅을 작성하기 전, 나는 다음과 같은 문제를 겪었다.

- Nest.js 를 Docker-compose 를 활용해 개발 중이었다.

- 그리고, Docker 컨테이너 안에서는 docker exec 명령어 자체가 불가능한 상황이었으며

- 따라서 DB 백업 명령어를 서버 안에서 직접 실행할 수 없는 문제가 발생했다.

 

즉, Docker 컨테이너 내부가 아닌 외부에서 백업 명령어를 수행시키면 될 일이다.

해결 방식은 다음과 같다.

- Nest.js는 백업 요청(.todo 파일)만 생성한다.

- 호스트(내 맥북)에서 .sh 파일(backup-watch.sh)이 백그라운드로 실행되게 하고

- .todo 파일이 생겼는지 감지하며

- 해당 파일이 감지된 경우, 진짜 docker exec 명령어로 백업을 수행한다.

정리하자면, 서버 컨테이너가 직접 docker 명령어를 사용하지 못하니,

내 맥북에서 감시하고 명령을 실행할 수 있도록 자동화된 Shell script(.sh)파일을 작성했다고 보면 좋다.

.sh 파일이란, shell script 파일로, 여러 터미널 명령어를 모아놓고, 한번에 실행할 수 있게 만든 스크립트.

 

폴더 구조는 다음과 같다

// 폴더 구조
root/
├── backup/
│   ├── db/                   # 실제 백업된 .sql.gz 파일 저장 폴더
│   └── tasks/                 # .todo 파일 저장 폴더 (백업 요청용)
│
├── backup-watcher.sh          # 호스트에서 돌아가는 감시 스크립트
│
└── src/
    └── data-backup/
        ├── data-backup.service.ts    # 백업 요청(create-backup.todo 파일 생성)
        └── data-backup.resolver.ts   # graphQL API (백업 요청, 삭제 등)

 

.sh 작성 요령에 대해서는 다음과 같다.

# backup-watcher.sh  

#!/bin/bash # 선언 명시

echo "[Watcher] 백업 감시" # echo 문자열 터미널에 출력

while true; do # 무한 루프 시작
  if [ -f backup/tasks/create-backup.todo ]; then # -f 파일 경로에 파일 존재 확인
    echo "[Watcher] 백업 요청 감지" # 존재한다면 문자열 출력 

    timestamp=$(date +"%Y-%m-%dT%H-%M-%S") # 파일 이름으로 쓸 시간 변수 저장
    backup_dir="backup/db" # 저장 위치
    backup_file="$backup_dir/neodb_${timestamp}.sql.gz" # 파일 이름

    mkdir -p $backup_dir # 해당 디렉토리가 있으면 새로 만들고 있으면 무시
    # 즉, backup/db 폴더가 없으면 새로 만듬

    echo "[Watcher] 백업 파일 생성 중: $backup_file" 

    docker exec {db_container_name} sh -c 'mysqldump -u {user_id} -p"{user_password}" {db_name}' | gzip > $backup_file
    # {} 안에는 해당되는 내용의 이름을 넣어주면 된다
    # docker exec docker 컨테이너 안에서 명령어 실행
    # mysqldump mysql db 백업 명령어
    # gzip 결과를 바로 압축
    # 해당 결과를 back_file 이름으로 저장

    if [ -s "$backup_file" ]; then # 파일 존재하고, 크기가 0보다 크면 true
      echo "[Watcher] 백업 성공: $backup_file"
    else
      echo "[Watcher] 백업 실패: 파일이 비어있음"
      rm -f "$backup_file" # 백업 파일 강제 삭제
    fi

    # todo 파일 삭제
    rm -f backup/tasks/create-backup.todo # 트리거로써 역할 완수했으니 todo파일 삭제
    echo "[Watcher] 백업 요청 완료 및 .todo 파일 삭제"

  fi
  sleep 3  # 3초마다 체크
done

 

서비스 로직은 위에서 언급한 것과 같이,

백업 파일 생성 기능이 실행되면 .todo 파일을 생성하기만 하면 된다.

// data-backup.service.ts

taskDir = path.resolve('backup/tasks'); // .todo 파일 위치

async createBackup(): Promise<boolean> {
  try {
    // tasks 폴더가 없으면 생성
    if (!fs.existsSync(this.taskDir)) {
      fs.mkdirSync(this.taskDir, { recursive: true });
    }

    // create-backup.todo 파일 경로 지정
    const todoPath = path.join(this.taskDir, 'create-backup.todo');

    // .todo 파일 생성 (백업 요청)
    fs.writeFileSync(todoPath, 'CREATE_BACKUP');

    return true;
  } catch (error) {
    throw new CusException();
  }
}

 

반응형

'개발 > 알쓸코잡' 카테고리의 다른 글

라즈베리파이 - OS 설치 방법과 원격 접속 방법(VNC)  (0) 2025.05.06
TCP & UDP  (0) 2023.04.22
Prisma (ORM)  (0) 2023.04.17
Gitflow  (0) 2023.03.04
CI / CD  (0) 2023.03.04
Comments