SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-09

Immich 백업 및 복구 방법: 데이터 손실 방지 가이드

Immich 백업 시 Postgres 데이터 디렉터리를 직접 복사하면 안 되는 이유와 타임라인이 비어 있는 현상을 해결하는 올바른 복구 절차를 설명합니다. v3.1.0 기준으로 원본 파일과 DB 덤프를 안전하게 관리하는 방법을 확인하십시오.

Immich 백업에 포함되어야 할 항목

Immich 백업은 동일한 시점에 캡처된 세 가지 요소로 구성됩니다. UPLOAD_LOCATION 경로 아래의 원본 파일, Postgres 데이터베이스의 SQL 덤프, 그리고 스택을 정의하는 .envdocker-compose.yml 파일입니다. 복구란 Immich 서버를 중지한 상태에서 해당 덤프를 새로운 데이터베이스에 다시 적용하고, 그 이후에 나머지 스택을 시작하는 과정을 의미합니다. 순서가 잘못되면 디스크에는 데이터가 가득 차 있지만 Immich 화면에는 타임라인이 비어 있는 상태가 됩니다.

이처럼 데이터를 분리하여 관리하는 이유는 Immich가 서로 정보를 공유하지 않는 두 곳에 상태를 저장하기 때문입니다. Postgres는 모든 앨범, 얼굴 클러스터, 공유 링크, 사용자 계정, API 키, 그리고 각 에셋의 저장 경로를 보관합니다. 파일 시스템은 실제 이미지 데이터를 보관합니다. 데이터베이스 없이 파일만 복구하면 Immich는 아무것도 표시하지 않습니다. 반대로 파일 없이 데이터베이스만 복구하면 모든 에셋이 깨진 이미지로 나타납니다.

여기에 기재된 명령어는 2026년 8월 초 기준 최신 릴리스인 Immich v3.1.0을 기준으로 작성되었습니다. 이 프로젝트는 업데이트 속도가 빠르며 문서화된 백업 절차도 여러 번 변경되었으므로, 명령어를 복사하기 전에 현재 실행 중인 버전을 반드시 확인하십시오. 아직 스택이 구성되지 않았다면 Immich 설치 가이드를 먼저 진행한 후 다시 돌아오시기 바랍니다.

경로가 가리키는 대상을 파악하십시오

.env에 있는 두 개의 변수가 이 페이지의 모든 설정을 결정합니다. UPLOAD_LOCATION는 Immich가 모든 미디어를 기록하는 상위 디렉터리입니다. DB_DATA_LOCATION는 Postgres 데이터 디렉터리입니다.

기본 제공되는 example.envUPLOAD_LOCATION=./library로 설정되는데, 이는 Immich가 그 내부library이라는 폴더를 생성하기 때문에 혼란을 초래하는 기본값입니다. 원본 파일은 최종적으로 ./library/library에 저장됩니다. 백업 스크립트가 실행 위치에 의존하지 않도록 절대 경로를 설정하십시오.

UPLOAD_LOCATION=/srv/immich/data
DB_DATA_LOCATION=/srv/immich/postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_VERSION=v3.1.0

UPLOAD_LOCATION 내부에는 Immich가 여러 폴더를 생성합니다. 그중 세 곳은 어떤 작업으로도 복구할 수 없는 데이터를 담고 있습니다.

  • library: 스토리지 템플릿에 따라 배치된 원본 파일
  • upload: 템플릿 레이아웃으로 아직 이동하지 않은 원본 파일 및 전송 중인 업로드 파일
  • profile: 사용자 프로필 사진

library를 잃어버리면 사진도 사라집니다. Immich는 원본 파일의 복사본을 다른 곳에 보관하지 않습니다.

Postgres 데이터 디렉터리를 복사하는 것이 백업이 아닌 이유

DB_DATA_LOCATION는 쉬운 대상처럼 보입니다. 디렉터리일 뿐이며 rsync으로 복사하면 오류 없이 완료되기 때문입니다. 하지만 두 가지 실패 사례를 보면 알 수 있듯이, 이는 여전히 백업이 아닙니다.

첫 번째 이유는 데이터 찢김(tearing) 현상입니다. Postgres는 모든 변경 사항을 먼저 WAL(write-ahead log)에 기록한 뒤, 체크포인트 시점에 테이블 파일에 반영합니다. 따라서 디스크의 파일들은 언제나 처리 중인 상태이며, 4분 동안 수행되는 순차 복사는 02:00에 첫 번째 파일을 읽고 02:04에 마지막 파일을 읽습니다. 이 두 파일은 동일한 트랜잭션에 속하지 않습니다. 결과물로 Postgres를 시작하면 PANIC: could not locate a valid checkpoint record 오류로 시작이 거부되거나, 시작되더라도 손상된 페이지를 처음 읽는 순간 invalid page in block 1234 of relation base/16384/... 오류와 함께 종료됩니다. 어느 경우든 해당 복사본으로는 복구가 불가능합니다.

두 번째 이유는 모든 프로세스를 먼저 중단하더라도 발생합니다. Postgres 데이터 디렉터리는 해당 데이터를 기록한 바이너리와 정확히 결합되어 있습니다. Immich는 데이터베이스 이미지를 다이제스트로 고정하며, 현재는 ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0입니다. 이는 두 개의 벡터 검색 확장 기능이 컴파일된 Postgres 14 버전입니다. 해당 빌드로 작성된 데이터 디렉터리는 다른 Postgres 메이저 버전에서는 열리지 않으며, 다른 확장 버전이 포함된 빌드에서도 열리지 않습니다. 복구 호스트는 이미지를 정확하게 재현해야 합니다. 반면 SQL 덤프는 텍스트 형식이므로 호환되는 모든 서버에서 재생할 수 있어 이러한 제약이 없습니다.

pg_dump은 데이터 찢김 문제를 근본적으로 회피합니다. 이 방식은 단일 MVCC(다중 버전 동시성 제어) 스냅샷 내에서 전체 데이터베이스를 읽으므로, 다른 쓰기 작업이 진행 중이더라도 특정 시점의 데이터베이스 상태를 그대로 볼 수 있습니다. 이것이 바로 덤프를 위해 Postgres를 중단할 필요가 없는 이유입니다.

백업에서 제외할 수 있는 항목

이 항목들은 재생성되므로 백업에서 제외해도 됩니다.

  • thumbs: 미리보기 및 썸네일 이미지
  • encoded-video: 트랜스코딩된 비디오
  • DB_DATA_LOCATION: 덤프 파일로부터 재구축 가능
  • model-cache Docker 볼륨: 머신러닝 모델, 필요 시 다시 다운로드 가능

이 항목들을 제외하는 것은 공짜로 얻는 이득이 아니라 일종의 트레이드오프입니다. 소규모 VPS에서 대규모 라이브러리의 썸네일과 트랜스코딩 파일을 재구축하려면 수 시간 동안 CPU를 사용해야 하며, 그동안 타임라인에는 회색 자리 표시자만 나타납니다. Administration > Jobs 메뉴에서 "Generate Thumbnails"와 "Transcode Videos"를 실행하여 누락된 에셋에 대해 작업을 수행할 수 있습니다. 백업 대상 저장소에 여유가 있다면 이 항목들을 포함하여 재구축 대기 시간을 줄이십시오. 저장 공간이 부족하다면 제외하고 추후 재구축 계획을 세우십시오. Immich 라이브러리 크기 산정에서는 원본 대비 이 폴더들이 얼마나 커지는지 다룹니다.

알아두어야 할 폴더가 하나 더 있습니다. UPLOAD_LOCATION/backups에는 Immich가 매일 02:00에 자동으로 생성하는 데이터베이스 덤프가 저장되며, 최근 14일 치가 유지됩니다. 이 설정은 Administration > Settings > Backup에서 변경할 수 있습니다. 이 덤프 파일은 용량을 거의 차지하지 않으며 매우 유용합니다. 다만 보호 대상인 라이브러리와 같은 디스크에 저장되므로, 서버 장애 시에는 도움이 되지 않으며 잘못된 마이그레이션 상황에서만 유용합니다. 직접 덤프를 생성하는 것이 좋습니다. 직접 실행한 덤프는 파일 스냅샷과 동일한 시점에 생성되므로 데이터 일관성을 유지할 수 있기 때문입니다.

데이터베이스 덤프 생성

docker exec -t immich_postgres pg_dump --clean --if-exists \
  --dbname=immich --username=postgres \
  | gzip > /srv/immich/backup/immich.sql.gz

immichpostgres을 변경했다면 본인의 DB_DATABASE_NAMEDB_USERNAME로 교체하십시오. --clean --if-exists은 모든 CREATE 앞에 DROP ... IF EXISTS을 추가하므로, 덤프를 복원할 때 첫 번째 객체에서 중단되지 않고 이미 객체가 존재하는 데이터베이스에 덮어쓰기 형태로 실행됩니다.

이제 백업 스크립트를 조용히 망치는 세부 사항을 다룹니다. 해당 명령어는 파이프라인이며, 셸은 파이프라인의 마지막 명령어에 대한 종료 상태만 보고합니다. 만약 pg_dump이 잘못된 비밀번호나 실행 중이지 않은 컨테이너로 인해 실패하더라도, gzip는 빈 스트림을 받아 완벽하게 유효한 gzip 파일을 생성하고 0을 반환하며 종료됩니다. 스크립트는 성공으로 기록되지만, 실제로는 20바이트짜리 백업 파일만 남게 됩니다. 모든 백업 스크립트 상단에 pipefail를 추가하십시오:

#!/usr/bin/env bash
set -euo pipefail

그다음 종료 코드만 신뢰하지 말고 결과를 직접 확인하십시오:

ls -lh /srv/immich/backup/immich.sql.gz
gunzip -c /srv/immich/backup/immich.sql.gz | head -n 3

정상적인 덤프의 첫 줄에는 -- PostgreSQL database dump이 포함되어 있습니다. 스크립트의 출력 결과와 상관없이, 파일 크기가 수백 바이트에 불과하다면 덤프는 실패한 것입니다.

덤프 파일 옆에 어떤 빌드가 해당 파일을 생성했는지 기록하십시오:

docker inspect --format '{{.Config.Image}}' immich_server > /srv/immich/backup/immich-version.txt

이 작업을 위해 .env에 의존하지 마십시오. 기본 파일 세트는 모든 3.x 릴리스를 따라가는 유동적인 태그인 IMMICH_VERSION=v3을 사용하므로, 어떤 빌드가 실제로 덤프를 생성했는지 알 수 없습니다. .env에서도 정확한 태그를 고정하십시오.

서버를 일시 중지한 후 restic으로 스냅샷 생성

Immich가 실행되는 동안 UPLOAD_LOCATION 아래의 파일들은 불변 상태가 아닙니다. 서버는 새로운 업로드를 기록하며, 스토리지 템플릿 작업은 디렉터리 간에 파일을 이동합니다. 백업 도구가 파일 쓰기 도중에 데이터를 읽으면, 해당 파일이 전체인 것처럼 저장하며 오류도 보고하지 않습니다. 백업이 진행되는 동안 서버 컨테이너를 중지하십시오.

docker stop immich_server

덤프 작업에 필요하므로 immich_postgres은 계속 실행 상태로 두어야 합니다. 서버를 다시 시작할 때까지 웹 인터페이스와 모바일 앱은 오프라인 상태가 되지만, 가정용 인스턴스의 경우 보통 03:00에는 문제가 되지 않습니다.

restic은 데이터를 외부로 전송하기 전에 중복 제거와 암호화를 수행하므로 이 작업에 적합합니다. 이 서버가 아닌 다른 위치의 저장소(repository)를 지정하십시오.

export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/srv/restic/immich
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init

객체 스토리지도 동일한 방식으로 작동하며, 하드웨어 외부로 복사본을 완전히 옮기려는 경우 더 나은 선택입니다.

export RESTIC_REPOSITORY=s3:https://s3.example.com/immich-backup
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
restic init

해당 엔드포인트는 직접 운영하는 MinIO 버킷이나 다른 머신, 또는 S3 호환 제공업체일 수 있습니다. 라이브러리와 동일한 디스크에 있는 저장소는 실수로 인한 삭제로부터만 보호할 뿐, 다른 위험에는 취약합니다.

그런 다음 중요한 데이터만 정확히 지정하여 스냅샷을 생성합니다.

restic backup \
  /srv/immich/backup/immich.sql.gz \
  /srv/immich/backup/immich-version.txt \
  /srv/immich/data/library \
  /srv/immich/data/upload \
  /srv/immich/data/profile \
  /srv/immich/.env \
  /srv/immich/docker-compose.yml
docker start immich_server

restic은 매 실행마다 전체 트리를 읽지만 이전에 본 적 없는 블록만 업로드합니다. 따라서 첫 번째 스냅샷은 전체 라이브러리를 전송하고, 이후의 모든 스냅샷은 당일 새로 추가된 사진만 전송합니다.

보존 정책 및 외부 보관이 필수적인 키

restic forget --prune --keep-daily 7 --keep-weekly 5 --keep-monthly 12

forget는 인덱스에서 스냅샷을 제거합니다. --prune은 해당 스냅샷이 마지막 참조였던 데이터를 실제로 삭제하는 역할을 합니다. --prune 없이 forget를 실행하면 스토리지 비용은 줄어들지 않습니다.

구조 검사는 비용이 저렴하므로 매주 실행하십시오.

restic check

이 명령은 리포지토리 메타데이터의 일관성을 검증합니다. 데이터 자체를 읽지는 않습니다. 한 달에 한 번은 샘플 데이터를 다시 읽어 기록된 해시값과 대조하십시오.

restic check --read-data-subset=5%

이 검사는 스토리지 백엔드에서 발생하는 무음 데이터 손상(silent corruption)을 잡아낼 수 있는 유일한 방법입니다. 실제 블록을 다운로드하여 체크섬을 다시 계산하기 때문입니다. 사진 라이브러리에 대해 전체 --read-data을 수행하면 리포지토리 전체를 다운로드해야 하므로, 종량제 객체 스토리지 환경에서는 상당한 비용이 발생합니다. 따라서 실제 운영 환경에서는 일부 데이터만 순차적으로 검사하는 방식을 사용합니다.

이제 사람들이 흔히 간과하는 부분입니다. restic 리포지토리 비밀번호는 복구할 수 없습니다. 비밀번호 재설정 기능이나 지원 티켓은 존재하지 않습니다. 복구하려는 서버의 /root/.restic-password 안에만 유일한 복사본이 있다면, 백업 데이터는 암호화된 무의미한 데이터 덩어리에 불과합니다. 객체 스토리지 액세스 키와 .envDB_PASSWORD도 마찬가지입니다. 이 모든 정보는 해당 서버의 생존 여부와 관계없는 곳에 보관하십시오. 종이에 인쇄하여 서랍에 넣어두거나, 다른 하드웨어에서 실행되는 비밀번호 관리자에 저장해야 합니다. 만약 해당 관리자 역시 자체 호스팅 중이라면 동일한 보호 조치가 필요하며, Vaultwarden 백업은 별도의 작업으로 관리해야 합니다.

Immich 복구 순서

복구 순서는 백업이 유효한지 아니면 빈 타임라인이 될지를 결정합니다. 새 호스트에서 다음 순서를 따르십시오.

먼저 설정을 복구하십시오. 설정 파일은 실행할 버전과 경로가 가리키는 위치를 알려줍니다.

restic restore latest --target /restore \
  --include /srv/immich/.env \
  --include /srv/immich/docker-compose.yml \
  --include /srv/immich/backup

시작하기 전에 버전을 고정하십시오. immich-version.txt을 읽고 .envIMMICH_VERSION을 해당 태그로 정확히 설정하십시오. 최신 릴리스는 당분간 그대로 두십시오. Immich는 패치 릴리스 사이에서도 다운그레이드를 지원하지 않습니다. 따라서 최신 서버가 이전 덤프를 기반으로 시작되어 마이그레이션을 수행하면 되돌릴 방법이 없습니다.

미디어를 복구하십시오.

restic restore latest --target /restore --include /srv/immich/data

그런 다음 library, upload, profile를 이동하여 이 호스트의 UPLOAD_LOCATION이 가리키는 위치 내부에 직접 배치하십시오. 호스트 경로는 변경될 수 있지만, compose 파일은 해당 디렉터리를 컨테이너 내부의 고정 경로에 바인딩하므로 내부 구조는 변경할 수 없습니다.

데이터베이스를 단독으로 시작하십시오. Postgres가 새로운 클러스터를 초기화하도록 DB_DATA_LOCATION을 비워 두십시오.

cd /srv/immich
docker compose pull
docker compose create
docker start immich_postgres
docker exec immich_postgres pg_isready --username=postgres

pg_isready은 초기 설정이 완료되면 accepting connections를 출력하며, 이는 몇 초 정도 소요됩니다. docker compose create은 컨테이너를 시작하지 않고 빌드만 수행합니다. 이 단계의 핵심은 Immich 서버가 아직 실행되어서는 안 된다는 점입니다. 빈 데이터베이스에서 서버가 시작되면 마이그레이션을 적용하고 새로운 스키마를 생성하며 관리자 계정 생성을 요구합니다. 이 상태에서 덤프를 복구하면 실행 중인 애플리케이션 아래에서 데이터가 덮어씌워집니다.

덤프를 다시 로드하십시오.

gunzip --stdout /restore/srv/immich/backup/immich.sql.gz \
  | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
  | docker exec -i immich_postgres psql --dbname=immich --username=postgres \
      --single-transaction --set ON_ERROR_STOP=on

이 과정에서 두 가지 요소가 중요한 역할을 합니다. sed이 존재하는 이유는 pg_dump가 안전 조치로 출력에 빈 search_path을 기록하기 때문입니다. 이렇게 하면 덤프 내의 정규화되지 않은 이름이 예상치 못한 스키마로 해석되는 것을 방지합니다. Immich의 벡터 검색 타입은 public에 위치하므로, 검색 경로가 비어 있으면 복구 시 벡터 타입으로 선언된 첫 번째 열에서 psql이 ERROR: type "vector" does not exist 오류와 함께 중단됩니다. public을 경로에 다시 추가하면 이 문제가 해결됩니다.

--single-transaction --set ON_ERROR_STOP=on은 전체 복구 과정을 하나의 트랜잭션으로 묶어 첫 번째 오류 발생 시 중단되도록 합니다. 이를 통해 데이터베이스가 완전히 복구되거나, 아니면 전혀 변경되지 않은 상태로 유지됩니다. 이 옵션이 없으면 중간에 실패했을 때 데이터베이스가 시작되고 로그인도 가능하지만, 알 수 없는 개수의 앨범이 누락된 상태가 될 수 있으며 이는 몇 주 후에야 발견될 수 있습니다.

이제 모든 서비스를 시작하십시오.

docker compose up -d
docker compose ps
docker logs -f immich_server

Immich Server is listening on과 같은 시작 메시지가 나타날 때까지 기다린 후, 2283 포트에 접속하여 이전 자격 증명으로 로그인하십시오. 사용자 계정은 덤프와 함께 복구되었습니다. 만약 로그인 페이지에서 첫 번째 관리자 계정 생성을 요구한다면 데이터베이스가 복구되지 않은 것입니다. 작업을 중단하고 psql 출력을 다시 확인하십시오.

공식 복구 지침의 시작 부분인 docker compose down -v에 관한 주의 사항이 하나 있습니다. -v은 명명된 볼륨(named volumes)을 삭제합니다. 기본 compose 파일에서 UPLOAD_LOCATIONDB_DATA_LOCATION는 바인드 마운트이므로 삭제되지 않습니다. 만약 이 중 하나라도 명명된 볼륨으로 변경했다면 해당 명령어가 사진을 삭제하게 됩니다. 명령어를 입력하기 전에 compose 파일을 먼저 확인하십시오.

복원 후 타임라인이 비어 있는 이유

타임라인은 데이터베이스 행을 기반으로 그려집니다. Immich는 부팅 시 upload/을 탐색하여 사진을 재발견하지 않습니다. 데이터베이스 행이 없는 파일은 소유자, 날짜, 앨범 정보가 없기 때문입니다. 따라서 가장 흔한 복원 실패 사례는 파일은 복구되었으나 데이터베이스가 누락된 경우입니다. Immich가 시작되면 빈 스키마를 생성하고, 디스크에는 사진이 가득 차 있음에도 불구하고 아무것도 없는 상태의 인스턴스를 제공합니다. 데이터는 손실되지 않았으나 보이지 않는 상태일 뿐입니다. 해결 방법은 위에서 설명한 대로 서버를 중지한 상태에서 덤프 파일을 다시 불러오는 것입니다.

두 번째 경우는 더 조용한 실패입니다. 데이터베이스는 복원되고 타임라인에 항목은 채워지지만, 모든 에셋을 열 수 없는 경우입니다. 이는 데이터베이스 행이 컨테이너에서 접근할 수 없는 경로를 가리키고 있음을 의미합니다. 보통 restic restore --target /restore 이후 library, upload, profile 경로가 한 단계 더 깊게 설정되어 파일이 제자리에 있지 않을 때 발생합니다. 추측하지 말고 컨테이너 내부에서 직접 확인하십시오.

docker exec immich_server ls /data

기본 compose 파일은 UPLOAD_LOCATION/data에 마운트합니다. 따라서 해당 경로를 나열하면 library, upload, profile가 보여야 합니다. 만약 디렉터리가 비어 있거나 엉뚱한 srv 폴더만 보인다면, 바인드 마운트가 잘못된 경로를 가리키고 있는 것이며 데이터베이스 행 자체는 정상입니다.

백업과 복원 간의 버전 일치

Immich는 릴리스가 잦고 그에 따라 스키마도 변경되므로, 덤프 파일에는 해당 파일을 생성한 서버의 스키마 정보가 포함됩니다.

이전 버전의 덤프를 최신 서버에 복원하는 작업은 일반적으로 성공합니다. 서버가 시작될 때 보류 중인 마이그레이션을 적용하여 스키마를 최신 상태로 업데이트하기 때문입니다. 이 경로는 릴리스 시퀀스를 따라 테스트됩니다. 여러 메이저 버전을 한 번에 건너뛰는 경우 문제가 발생할 수 있으며, 프로젝트는 메이저 릴리스마다 변경 사항을 적용하고 이를 변경 로그(changelog)에 문서화합니다.

최신 버전의 덤프를 이전 버전의 서버에 복원하는 것은 불가능합니다. 덤프에는 이전 버전의 코드가 인식하지 못하는 테이블과 컬럼이 포함되어 있으며, Immich는 패치 릴리스 사이에서도 다운그레이드를 지원하지 않는다고 명시하고 있습니다. 실행할 수 있는 롤백 명령어도 존재하지 않습니다.

따라서 안전한 복원 방법은 지루하지만 정석적인 절차를 따르는 것입니다. 덤프를 생성했을 때와 동일한 버전을 실행하여 데이터를 복구하고, 로그인한 뒤 타임라인이 완전한지 확인하십시오. 그 이후에 업그레이드를 진행해야 합니다. 한 번에 하나의 릴리스씩 업그레이드하며, 각 단계마다 IMMICH_VERSION를 수정하고 docker compose pull && docker compose up -d를 실행하십시오. 일주일 치 덤프를 보관하는 것도 도움이 됩니다. 최신 덤프가 업그레이드 실패 중에 생성된 것이라면, 어제 생성된 덤프를 저장소에서 사용할 수 있기 때문입니다.

매달 백업을 검증하십시오

복원해 본 적 없는 백업은 추측에 불과합니다. 매달 한 번씩 일회용 인스턴스에 백업을 복원하고 사진을 확인하십시오. 이 훈련은 약 20분 정도 소요되며, 이 페이지의 나머지 내용을 실제 복구 계획으로 바꿀 수 있는 유일한 방법입니다.

restic snapshots
restic stats latest

snapshots 명령으로 어젯밤 실행 기록을 확인해야 합니다. stats latest 명령은 몇 MB가 아닌, 실제 라이브러리 크기와 비슷한 용량을 보고해야 합니다.

가급적 여분의 호스트에 있는 임시 디렉터리로 복원하십시오.

restic restore latest --target /tmp/immich-drill

복원된 세트에서 docker-compose.yml.env를 복사한 뒤, 복사본에서 세 가지를 변경하십시오. UPLOAD_LOCATIONDB_DATA_LOCATION/tmp/immich-drill 하위의 디렉터리를 가리키도록 설정합니다. 웹 포트는 2283:2283 대신 12283:2283과 같이 다른 포트로 게시하십시오. 기본 compose 파일은 immich_server과 같은 이름을 하드코딩하므로 container_name: 줄을 삭제하십시오. 그렇지 않으면 동일한 호스트에서 두 번째 스택이 첫 번째 스택과 충돌하여 Docker가 생성을 거부합니다.

위에서 설명한 복원 절차를 실행하십시오. 데이터베이스만 복원하고 덤프를 재생한 다음 docker compose up -d을 실행합니다. 이제 데이터가 정상임을 증명하는 네 가지 확인 작업을 수행하십시오.

  1. 훈련 전 사용하던 비밀번호로 로그인하십시오. 계정이 작동한다면 덤프가 정상적으로 복원된 것입니다.
  2. 타임라인을 열고 가장 오래된 달로 스크롤하십시오. 전체 날짜 범위에 걸쳐 자산이 보인다면 최근 데이터뿐만 아니라 모든 행이 복구된 것입니다.
  3. 사진 하나를 전체 크기로 열고 원본을 다운로드하십시오.
  4. sha256sum 명령을 사용하여 라이브 라이브러리에 있는 동일한 파일과 비교하십시오. 해시값이 일치한다면 restic을 거치는 과정에서 데이터가 손실 없이 보존된 것입니다.

그런 다음 훈련 디렉터리에서 docker compose down -v를 실행하여 훈련 환경을 정리하고 /tmp/immich-drill을 삭제하십시오. 이 작업의 가치는 다음 달에 다시 수행하는 데 있으므로, 날짜를 눈에 잘 띄는 곳에 기록해 두십시오. 어떤 사진 서버를 사용할지 결정 중이라면 PhotoPrism과 Immich 비교 문서를 통해 이 부분에서 두 서비스가 어떻게 다른지 확인해 보십시오.

FAQ

Immich를 백업하려면 서비스를 중단해야 합니까?

immich_server은 중단하고 immich_postgres는 계속 실행해도 됩니다. 데이터베이스는 일시 정지할 필요가 없습니다. pg_dump은 MVCC 스냅샷 내부를 읽으므로, 다른 쓰기 작업이 진행 중이라도 단일 시점의 일관된 데이터를 조회하기 때문입니다. 파일을 백업할 때 중단이 필요한 이유는 따로 있습니다. 서버가 새로운 업로드를 기록하거나 스토리지 템플릿 작업이 디렉터리 간 파일을 이동시키는 도중에 백업 도구가 파일을 읽으면, 쓰기가 완료되지 않은 손상된 복사본이 저장될 수 있기 때문입니다. 스냅샷 생성 전 docker stop immich_server를 수행하고 생성 후 docker start immich_server를 수행하면 이러한 경쟁 상태를 방지할 수 있습니다.

pg_dump를 실행하는 대신 Postgres 데이터 폴더를 복사해도 됩니까?

아니요. 실행 중인 데이터 디렉터리를 실시간으로 복사하면 서로 다른 시점의 파일들을 읽게 되어 일관된 상태가 보장되지 않습니다. 이 경우 Postgres는 시작 시 PANIC: could not locate a valid checkpoint record 오류를 발생시키거나, 나중에 페이지 손상으로 인해 실패합니다. 모든 서비스를 중단하고 복사하더라도 특정 데이터베이스 빌드에 종속됩니다. Immich는 특정 버전의 벡터 검색 확장 기능을 포함한 Postgres 14 이미지를 사용하므로, 해당 디렉터리는 다른 환경에서 열리지 않습니다. SQL 덤프는 일반 텍스트 형식이므로 호환되는 모든 서버에서 복구할 수 있습니다.

복구 후 Immich 타임라인이 비어 있는 이유는 무엇입니까?

타임라인은 데이터베이스 행을 기반으로 생성되는데, 데이터베이스 없이 파일만 복구했기 때문입니다. Immich는 upload/을 스캔하여 사진을 다시 검색하지 않으므로, 데이터베이스 행이 없는 파일은 표시되지 않습니다. 사진 파일 자체는 그대로 남아 있습니다. 서버를 중단하고 새로 초기화된 Postgres에 덤프를 다시 적용한 뒤 스택을 시작하십시오. 반대로 타임라인은 정상인데 사진이 열리지 않는다면, library, upload, profile이 컨테이너에 바인딩된 디렉터리 내부에 직접 위치하지 않은 경우입니다. docker exec immich_server ls /data 명령으로 경로를 확인하십시오.

Immich 폴더 중 백업에서 제외할 수 있는 것은 무엇입니까?

thumbsencoded-video은 원본 파일로부터 다시 생성할 수 있고, DB_DATA_LOCATION는 덤프 파일로부터 재구축할 수 있으므로 백업 세트에 포함할 필요가 없습니다. 이를 제외하면 백업 시 저장 공간을 절약할 수 있지만, 복구 후 재구축하는 데 시간이 소요됩니다. 대규모 라이브러리의 미리보기와 트랜스코딩을 다시 생성하려면 CPU 자원을 몇 시간 동안 사용해야 하며, 이는 Administration > Jobs 메뉴에서 누락된 자산을 대상으로 실행할 수 있습니다. 절대 제외해서는 안 되는 것은 library, upload, profile이며, 이곳에 모든 원본 파일의 유일한 복사본이 저장됩니다.

Immich 덤프를 더 최신 버전으로 복구할 수 있습니까?

일반적으로 가능합니다. 서버가 시작될 때 보류 중인 마이그레이션을 적용하여 스키마를 최신 상태로 업데이트하기 때문입니다. 반대의 경우는 실패합니다. Immich는 패치 릴리스 간에도 다운그레이드를 지원하지 않으므로, 더 최신 릴리스에서 생성된 덤프를 이전 버전의 서버에 로드할 수 없습니다. 덤프를 생성했을 때와 동일한 버전으로 고정된 IMMICH_VERSION을 사용하여 복구하고, 타임라인이 완전한지 확인한 뒤 업그레이드하십시오. 기본값인 IMMICH_VERSION=v3은 버전 정보를 알 수 없는 유동적인 태그이므로, docker inspect --format '{{.Config.Image}}' immich_server를 사용하여 각 덤프 옆에 버전을 기록해 두는 것이 좋습니다.