fix: make OCR portable and reliable across AMD64 and ARM64 (#519)

* fix: make OCR portable and reliable

* fix: harden OCR installation portability

* fix: pin OCR partials across downloads

* fix: make OCR execution reliably asynchronous

* fix: harden OCR portability and docs routes

* fix: preserve decoder and docs safeguards
This commit is contained in:
SnapOtter
2026-07-15 03:34:24 +08:00
committed by GitHub
parent 58121f205f
commit 991c981529
409 changed files with 67151 additions and 8076 deletions
+42 -10
View File
@@ -1,8 +1,8 @@
---
description: "Docker로 SnapOtter를 프로덕션에 배포. 하드웨어 요구 사항, GPU 설정, Nginx, Traefik, Cloudflare용 리버스 프록시 구성."
i18n_source_hash: 6b6957060fa6
i18n_provenance: machine
i18n_output_hash: 6f74c9877d90
i18n_output_hash: a82cc0e64487
i18n_source_hash: e0d8d5f6fc87
i18n_provenance: human
---
# 배포 {#deployment}
@@ -11,6 +11,12 @@ SnapOtter는 SnapOtter 앱 이미지, PostgreSQL 17, Redis 8로 구성된 3-컨
GPU 설정, Docker Compose 예제, 버전 고정에 대해서는 [Docker 이미지](./docker-tags)를 참고하라.
<!-- korean-ocr-contract:start -->
::: info 한국어 OCR 호환성
빠른 OCR은 `auto`, `en`, `de`, `es`, `fr`, `zh`, `ja`를 지원하지만 한국어(`ko`)는 지원하지 않습니다. 한국어에는 정확한 OCR 팩과 `balanced` 또는 `best`가 필요합니다. 이 팩은 공식 Linux amd64 및 arm64 컨테이너에서 작동하며 NVIDIA 호스트에서도 OCR은 CPU에서 실행됩니다. 지원되지 않는 시스템은 명시적인 호환성 오류를 반환하며 조용히 `fast`로 대체하지 않습니다. 한국어에 `fast` 또는 이전 `tesseract` 별칭을 지정하면 큐에 넣기 전에 `FEATURE_INCOMPATIBLE``fast-korean-unsupported`로 거부됩니다.
:::
<!-- korean-ocr-contract:end -->
## 빠른 시작 (CPU) {#quick-start-cpu}
```yaml
@@ -113,7 +119,7 @@ docker compose up -d
## 빠른 시작 (NVIDIA CUDA) {#quick-start-nvidia-cuda}
AI 도구(배경 제거, 업스케일링, 얼굴 보정, OCR)에 NVIDIA CUDA 가속을 사용하려면:
지원되는 AI 도구의 NVIDIA CUDA 가속의 경우(배경 제거, 업스케일링, 얼굴 향상):
```yaml
# docker-compose-gpu.yml - Requires: NVIDIA GPU + nvidia-container-toolkit
@@ -251,10 +257,10 @@ deploy:
|---|---|
| CPU | 4 코어 |
| RAM | 4 GB |
| 디스크 | 3 GB (이미지) + 24 GB (AI 모델) + 작업 공간 |
| Disk | 3GB(이미지) + 약 20GB(모든 옵션 AI ) + 작업 공간 |
| GPU | 필요 없음 (CPU 폴백) |
**RAM을 4 GB로 끌어올리는 것은 AI 번들 설치다.** AI를 설치하지 않으면 앱은 대략 360 MB에서 유휴 상태로 있지만, 7개 번들을 모두 설치하면 ~2.6 GB의 상주 메모리를 유지한다. Python AI 사이드카가 시작 시 모델(배경 제거, 업스케일링, OCR, 전사, 얼굴 감지, 복원)을 미리 로드하기 때문이다. 비AI 설치는 가볍게 유지되지만, AI 설치에는 4 GB 이상이 필요하다.
**더 큰 AI 번들 설치하고 실행하면 RAM 의 권장 용량이 4GB로 늘어납니다.** 옵션 팩을 설치하지 않으면 앱이 약 360MB 정도 유휴 상태가 됩니다. 레거시 Python 도구는 sidecar 를 공유하는 반면 정확한 OCR 는 활성 불변 생성에 고정된 전용 장기 dispatcher 를 사용합니다. 활성화하기 전에 설치 프로그램은 후보에서 smoke test 를 실행합니다. 그런 다음 원자적으로 새로운 dispatcher 로 전환하고 garbage collection 이전에 이전 dispatcher 를 배출합니다. 모든 공식 정확한 OCR 아티팩트는 4 GiB cgroup 내에서 최악의 경우 release suite 를 통과해야 하며, 4GB 호스트 권장 사항은 Node.js 애플리케이션, Postgres, Redis, 대기열 및 동시 작업을 위한 여유 공간을 남겨둡니다.
대부분의 AI 도구는 CPU에서도 충분히 사용할 수 있으나, 일부는 GPU가 절실하다. 최신 4코어 CPU에서 측정한 값:
@@ -271,7 +277,7 @@ SnapOtter는 의도적으로 이러한 모델 다운로드를 Docker 이미지
일부 도구는 둘 이상의 공유 번들에 의존한다. 예를 들어 여권 사진은 `background-removal``face-detection`가 모두 필요하다. `background-removal`가 이미 설치되어 있다면, 여권 사진을 활성화할 때 누락된 `face-detection` 번들만 다운로드한다. 동일한 재사용이 모든 AI 도구에 적용된다.
AI 모델 다운로드 크기:
선택적 AI 팩 스토리지 추정치:
| 번들 | 디스크 크기 |
|---|---|
@@ -279,9 +285,16 @@ AI 모델 다운로드 크기:
| 업스케일 + 얼굴 보정 + 노이즈 제거 | 5-6 GB |
| 얼굴 감지 | 200-300 MB |
| 객체 지우기 + 컬러화 | 1-2 GB |
| OCR | 5-6 GB |
| 정확한 OCR(`balanced`/`best`) | ~208-234 MiB 다운로드 / ~409-488 MiB 설치됨 |
| 사진 복원 | 4-5 GB |
| **모든 번들** | **~24 GB** |
| 전사 | ~600MB |
| **모든 번들** | **~20GB 설치됨** |
Fast OCR는 Tesseract를 통해 이미지에 내장되며 약 25 MiB를 추가합니다. 선택 사항인 OCR 팩이나 그 팩의 4 GiB 메모리 요구 사항은 적용되지 않습니다. 고정확도 팩은 공식 Linux amd64 및 arm64 컨테이너에서 사용할 수 있으며 CPU에서 ONNX Runtime를 실행합니다. NVIDIA 호스트도 동일한 CPU OCR 런타임을 사용하므로 OCR는 CUDA 버전이나 GPU 아키텍처에 의존하지 않습니다. 고정확도 런타임에는 최소 4 GiB의 유효 메모리(구성된 컨테이너 cgroup 제한, 없으면 호스트 메모리)가 필요합니다. SnapOtter는 팩을 다운로드하기 전에 서명된 최소 호환성보다 메모리가 적은 시스템을 거부합니다. libc 및 Python ABI를 보장할 수 없는 bare-metal 또는 사전 구축 아카이브에서도 고정확도 팩 설치가 거부됩니다.
동일한 `DATA_DIR`를 공유하는 레플리카는 동일한 CPU 아키텍처를 사용해야 합니다. 노드 어피니티를 사용해 다중 레플리카 배포를 호환 노드에 고정하세요. amd64/arm64 혼합 레플리카에는 별도의 데이터 볼륨과 독립적인 SnapOtter 배포가 필요합니다.
정확한 런타임은 하나의 활성 세대를 유지하고 활성화 후 다운로드 캐시를 제거합니다. 이 릴리스의 경우 첫 번째 설치에는 아카이브와 스테이징을 위해 일시적으로 대략 620-720 MiB 가 필요하며, 이전 세대가 활성 상태를 유지하는 동안 업그레이드는 1.2 GiB 근처에서 최고에 달할 수 있습니다. 설치 프로그램은 다운로드하거나 추출하기 전에 서명된 인덱스와 현재 세대의 정확한 요구 사항을 계산하며, 데이터 볼륨이 너무 작으면 조기에 실패합니다.
```yaml
deploy:
@@ -353,7 +366,6 @@ SnapOtter는 20+ 카메라 브랜드의 RAW 파일, 전문 형식(PSD, EPS, Open
- **콘텐츠 인식 크기 조정**은 caire 바이너리의 한계 때문에 큰 이미지(>5 MP)에서 충돌한다. 더 작은 이미지에서는 정상 작동한다.
- **HEIF 디코드**는 13-23초가 걸린다. HEIC(Apple 변형)는 0.3-0.9초로 훨씬 빠르다.
- **OCR 일본어**는 PaddlePaddle MKLDNN 버그 때문에 CPU에서 실패한다. GPU에서는 작동한다.
- **업스케일**은 작은 이미지를 넘어서면 CPU에서 타임아웃된다. 실용적으로 쓰려면 GPU가 필요하다.
- **CodeFormer** 얼굴 보정은 GFPGAN보다 상당히 느리다(GPU에서 53초 대 2초). 대부분의 사용 사례에는 GFPGAN이 권장된다.
@@ -434,6 +446,26 @@ securityContext:
| `SESSION_DURATION_HOURS` | `168` | 로그인 세션 수명 (7일) |
| `CORS_ORIGIN` | (비어 있음) | 쉼표로 구분된 허용 오리진, 동일 오리진이면 비워 둠 |
### 아웃바운드 프록시 및 개인 CA {#outbound-proxy-and-private-ca}
공식 컨테이너는 Node의 환경 프록시 지원을 활성화합니다. SnapOtter 가 회사 프록시를 통해 OCR 런타임 저장소 또는 기타 HTTPS 서비스에 연결해야 하는 경우 `HTTPS_PROXY`(및 필요한 경우 `HTTP_PROXY`)를 설정하세요. `NO_PROXY`를 Postgres, Redis 및 내부 개체 스토리지와 같이 직접 연결해야 하는 쉼표로 구분된 호스트 목록으로 설정합니다.
프록시 또는 내부 서비스가 개인 인증 기관에 의해 서명된 경우 CA 인증서를 읽기 전용으로 마운트하고 `NODE_EXTRA_CA_CERTS`를 가리키도록 합니다. 노드 프로세스가 시작될 때 파일이 존재해야 합니다.
```yaml
services:
app:
environment:
HTTPS_PROXY: http://proxy.example.internal:3128
HTTP_PROXY: http://proxy.example.internal:3128
NO_PROXY: postgres,redis,minio,localhost,127.0.0.1
NODE_EXTRA_CA_CERTS: /etc/snapotter/custom-ca.pem
volumes:
- ./company-ca.pem:/etc/snapotter/custom-ca.pem:ro
```
프록시 자격 증명을 Compose 파일 외부(예: 보호된 `.env` 파일 또는 비밀)에 보관하세요. TLS 확인을 비활성화하지 마십시오. 서명된 OCR 인덱스는 릴리스 메타데이터를 인증하는 반면 일반 TLS 확인은 여전히 ​​전송 및 기타 모든 아웃바운드 요청을 보호합니다.
## 헬스 체크 {#health-check}
컨테이너에는 내장 헬스 체크가 포함되어 있다: