Skip to content

Feature/342 docker image size - #344

Merged
HeechanKim-Genon merged 2 commits into
developfrom
feature/342-docker-image-size
Aug 7, 2026
Merged

Feature/342 docker image size#344
HeechanKim-Genon merged 2 commits into
developfrom
feature/342-docker-image-size

Conversation

@inoray

@inoray inoray commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

feat(#342): 도커 이미지 용량 최적화 — 4개 Dockerfile 공통 정비 + .dockerignore 신설

개요

전처리기/코드서빙 도커 이미지가 필요 이상으로 커진 원인을 찾아 제거한다. 대상은 이 레포의
빌드 대상 Dockerfile 4개 전부이며, 애플리케이션 코드는 한 줄도 바뀌지 않는다.

파일 용도
genon/preprocessor/docker/Dockerfile.standard 전처리기 오픈소스 빌드
genon/preprocessor/docker/Dockerfile.synap 전처리기 엔터프라이즈(Synap) 빌드 — standard 와 동일한 변경
build-script/code-serving-doc-parser/Dockerfile 코드서빙 CPU
build-script/code-serving-doc-parser/Dockerfile.gpu 코드서빙 GPU

여기에 레포 루트 .dockerignore 를 새로 추가한다(지금까지 없었다).

배경 — 커진 원인은 세 갈래였다

① 안 쓰는 자산을 받아왔다. docling 기본 모델 세트의 code_formula(506MB), HF 레포
mncai/doc_parser_models 전체(846MB) 중 실제 사용은 MiniLM 토크나이저 하나, dev 의존성 그룹
(약 100MB), torch 의 C++ 헤더/테스트 픽스처(141MB), 참조가 0건인 tessedata.tar.gz(35MB).

② 지웠는데 레이어가 회수되지 않았다. COPY 로 가져와 다음 RUN 에서 rm 하면 상위 레이어에
whiteout 만 생기고 원본 레이어는 그대로 남는다. 더 큰 건 runtime 마지막의
chown -R … /app /models /app/nltk_data — overlayfs 에서 소유권만 바꿔도 전 파일이 copy-up 되어
같은 데이터를 담은 5.2GB 레이어가 하나 더 생겼다. 이미지 내용은 6.8GB인데 레이어 합이 12.5GB가
된 주된 이유다.

③ CUDA 휠을 받았다가 버렸다. CPU 빌드가 PyPI 기본(CUDA) torch 를 먼저 설치해 nvidia 휠 15종 +
triton 약 4GB 를 내려받은 뒤, 바로 다음 단계에서 CPU 휠로 갈아끼우며 전부 폐기했다. GPU 빌드는 더
심해서 기본 CUDA torch 약 4GB 를 받고 다시 cu124 인덱스에서 약 4GB 를 받아 덮어썼다(총 약 8GB, 절반 폐기).

그리고 ③ 을 파고들다 실제 버그 1건이 나왔다 — 아래 "하드코딩된 nvidia 제거 목록" 항목.

주요 변경

1) 레이어 회계 (4개 파일 공통)

runtime 의 전역 chown -R 제거 → COPY --chown 으로 전환.
.venv(2.6GB) + /models(2.2GB) + nltk_data + hwp_sdk 를 복사한 뒤 소유권만 바꾸던 마지막
RUN chown -R 을 없애고, 각 COPY--chown=${UID}:${GID} 를 준다. 남은 chown 은 작은 것만:

  • /app, /app/nltk_data — base 단계에서 root 로 미리 만들어진 디렉토리 자체의 소유권은
    COPY --chown 이 바꾸지 않으므로 비재귀 chown 으로 보정
  • site-packages/hwp_sdk — 심볼릭 링크 자체 소유권(chown -h)
  • find /app -maxdepth 1 -user 0 -exec chown … {} + — 누락분 방어
  • /run /var/log /etc/supervisor /app/.cache /app/.config /app/.local /app/tmp /tmp/xdg — KB 단위라 -R 무해

resources 디렉토리 통째 COPY → bind mount.
필요한 건 HCRBatang.ttf.tar.gz 뿐인데 디렉토리를 통째로 복사해 참조 0건인 tessedata.tar.gz(35MB)
까지 들어왔고, 폰트 tarball 을 다음 레이어에서 rm 해도 COPY 레이어는 회수되지 않았다.
(한국어 tessdata 는 apt tesseract-ocr-kor 로 이미 들어온다.)

RUN --mount=type=bind,source=genon/preprocessor/resources/HCRBatang.ttf.tar.gz,target=/tmp/HCRBatang.ttf.tar.gz \
    set -eux; mkdir -p /usr/share/fonts && tar zxf /tmp/HCRBatang.ttf.tar.gz -C /usr/share/fonts/ && fc-cache -f -v

회수된 COPY 레이어: standard/synap 48MB, code-serving 11.6MB.

cache mount 가 걸린 apt RUN 의 rm -rf /var/lib/apt/lists/* 제거.
/var/cache/apt/var/lib/apt/lists 를 cache mount 로 잡은 RUN 은 애초에 그 내용이 이미지
레이어에 포함되지 않는다. 크기 이득은 0이면서 다음 빌드가 재사용할 apt 인덱스만 파괴하고 있었다.
⚠️ cache mount 가 없는 RUN(rhwp 빌더 등)의 rm 은 실제로 레이어를 줄이므로 그대로 유지했다.

2) 모델 자산 선별

docling-tools models download 목록 명시. 인자 없이 호출하면 기본 세트를 전부 받는다.

ARG DOCLING_MODELS="layout tableformer picture_classifier easyocr"
  • 제외: code_formula(ds4sd--CodeFormula, 506MB). do_code_enrichment /
    do_formula_enrichmentpipeline_options.py 에서 기본 False 이고 이를 켜는 config 키·코드가
    없어 CodeFormulaModelenabled=False 로만 생성된다.
    ⚠️ 이 판단은 현재 제품 기능 기준이다. docling CLI 자체에는 enrichment 를 켜는 옵션이 있으므로,
    향후 facade 가 이를 노출하거나 코드서빙에서 런타임 clone 되는 서비스 코드가 켜면
    오프라인 환경에서 모델이 없어 실패한다. 그때는 목록에 다시 넣어야 한다.
  • 유지 근거 (docling/utils/model_downloader.pywith_* 플래그와 1:1):
    • layout → PDF 는 genos_layout(dotsocr)을 쓰지만 PPT/PPTX 경량 파이프라인이 bare
      PdfPipelineOptions()LayoutModel 을 만들어 실제 로드한다
    • tableformerlayout_model_type: docling_layout 배포에서 필요
    • picture_classifierchart.enable opt-in (16MB)
    • easyocr → CRAFT 검출기(craft_mlt_25k 83MB) 등. 목록에서 빼면 아래 korean_g2.zip
      단계만 남아 검출기가 사라진다

HF 레포 부분 다운로드. mncai/doc_parser_models 에서 실제로 쓰는 건 MiniLM 토크나이저 폴더
하나뿐인데 전체(846MB)를 받고 있었다 — docling-models(506MB)는 참조 0건(TableFormer 는
ds4sd--docling-models 를 쓴다), docling-layout-old(164MB)는 MNCAI_CUSTOM_LAYOUT 전용 경로이나
model_spec 을 그 값으로 바꾸는 코드가 없다. 게다가 두 번째 download--local-dir 이 이미 받은
폴더를 다시 가리켜 동명 하위 디렉토리가 중첩 생성
됐다(88MB 중복). 코드는 바깥쪽만 사용한다.

huggingface-cli download mncai/doc_parser_models \
  --include "sentence-transformers-all-MiniLM-L6-v2/*" --local-dir /models/doc_parser_models

EasyOCR 한국어 모델 캐시 조건 수정 (버그). 조건이 /models/EasyOcr/korean_g2.zip 존재를 봤는데
zip 은 캐시 마운트 /root/.cache/easyocr_korean/ 에 저장되므로 그 경로에는 zip 이 절대 생기지 않았다
조건이 항상 참 → 캐시가 있어도 매 빌드 재다운로드. 캐시 경로를 보도록 고치고, unzip
조건 밖으로 뺐다(캐시에 zip 이 있어도 /models/EasyOcr 는 새 레이어라 매번 풀어야 한다).
(code-serving Dockerfile 은 처음부터 캐시 경로를 검사해 올바르게 동작하고 있었다.)

죽은 캐시 마운트 제거. --mount=type=cache,target=/root/.cache/models 를 아무도 쓰지 않았다
(docling-tools 는 -o /modelsHF_HOME 을 쓴다 — 실제로 그 캐시는 4KB로 비어 있었다).

3) venv 다이어트

uv sync --no-dev (전처리기 2개 파일) — dev 그룹(pytest/mypy/debugpy/ipykernel/pre-commit …)은
런타임 이미지에 불필요하다. 붙이지 않으면 uv 가 기본 설치해 약 100MB(debugpy 18M, mypy+mypyc .so
47M 등)가 들어온다. 코드서빙은 uv pip install . 방식이라 애초에 dev 그룹을 설치하지 않는다.

CPU/GPU 휠을 처음부터 올바르게 받는다. 도구별로 방법이 다르다:

파일 방식
Dockerfile.standard / .synap uv sync 에는 --torch-backend 가 없어 → uv.lock 에서 뽑은 --no-install-package nvidia-… triton + torch/torchvision 제외 후, CPU 휠 재설치
code-serving CPU uv pip install . --torch-backend=cpu
code-serving GPU uv pip install . --torch-backend=cu124 (재설치 단계 삭제)

standard 쪽 제외 목록도 하드코딩하지 않고 uv.lock 에서 추출한다:

EXCL=$(grep -oE '^name = "(nvidia-[A-Za-z0-9._-]*|triton)"' uv.lock \
       | sed 's/^name = "//; s/"$//' | sed 's/^/--no-install-package /' | tr '\n' ' ')
uv sync --frozen --no-dev --no-install-package torch --no-install-package torchvision ${EXCL}

🔴 하드코딩된 nvidia 제거 목록 삭제 — 이 PR 의 실질 버그픽스.
기존 코드는 nvidia-cublas-cu12 처럼 -cu12 접미사 목록을 박아두고 끝에 || true 를 붙였다.
버전 핀이 없던 code-serving 쪽에서 torch 2.13 이 잡히며 CUDA 13 휠로 패키지명이 바뀌자
(nvidia_cublas 접미사 없음, nvidia_cudnn_cu13, nvidia_nccl_cu13 …) 이름이 하나도 일치하지 않아
uninstall 이 전부 실패했고, || true 가 그 실패를 삼켜 CPU 이미지에 CUDA 라이브러리 2.7GB 가 조용히
실려 나가고 있었다.

기존 smoke test 는 torch.version.cuda is None 만 보므로 이걸 잡지 못했다 — torch 자체는 CPU 휠로
교체됐고 딸려온 nvidia 휠만 남아 있었기 때문이다.

→ 설치된 목록에서 이름을 뽑아 지우고, 실패를 감추지 않고, 잔존 시 빌드를 실패시킨다:

uv pip list --python ${APP_VENV}/bin/python --format=freeze \
  | sed -n 's/^\(nvidia[A-Za-z0-9._-]*\|triton\)==.*/\1/p' | tee /tmp/cuda_pkgs.txt
xargs -r uv pip uninstall --python ${APP_VENV}/bin/python < /tmp/cuda_pkgs.txt
uv pip list … | grep -iE '^(nvidia|triton)' && { echo "[ERROR] nvidia/triton 잔존"; exit 1; } || true

torch 런타임 미사용 자산 제거 — 약 141MB (torch/test 81M + torch/include 60M).
C++ 헤더와 테스트 픽스처로 추론 경로에서는 쓰이지 않는다.
⚠️ torch/bin(50MB)은 지우면 안 된다. torch/__init__.py 가 import 시점에 _manager_path()
torch/bin/torch_shm_manager 존재를 무조건 확인하고 없으면 RuntimeError 로 죽는다
(DataLoader 를 쓰지 않아도 발생 — 실제로 제거했다가 import torch 부터 실패했다).

opencv headless 통일 — 약 116MB.
opencv-python(non-headless)과 opencv-python-headless 가 둘 다 해석돼 들어온다(전자는
unstructured-inference + 자체 pyproject, 후자는 docling-ibm-models/easyocr). 같은 cv2 모듈을
제공하므로 opencv_python.libs 가 순수 중복이다. 첫 파티 코드에 import cv2 는 한 건도 없고,
cv2 를 쓰는 패키지들은 headless 로 충분하다. 실측: 파일시스템 5.20GB → 5.08GB.

  • ⚠️ 순서: opencv-python 을 지우면 공유되는 cv2/ 파일까지 사라지므로 반드시 뒤에 headless 를 --reinstall
  • ⚠️ 버전 핀: uv pip install 은 lock 을 참조하지 않아 버전을 안 주면 최신(현재 5.0.x)을 가져와
    lock 의 4.11 에서 메이저 점프가 일어난다. 하드코딩 대신 uv.lock 에서 뽑아 핀한다.
  • 설치 후 import cv2 / import unstructured_inference / opencv_python.libs 잔존 검사로 자기검증
  • Dockerfile.gpu 는 이 블록이 builder apt RUN 뒤에 와야 한다(ubuntu:22.04 최소 구성이라
    그 전에는 libglib2.0-0 이 없어 import cv2 가 ImportError)

4) 베이스 이미지 / 빌드 환경

GPU runtime 베이스 다운그레이드 — 약 1.9GB.
nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.0412.4.1-base-ubuntu22.04.
torch 는 pip nvidia 휠(uv.lock 에 15개, cuDNN 포함)에 링크되므로 베이스가 주는 시스템 CUDA/cuDNN 은
쓰이지 않는다 — CUDA 를 사실상 두 번 싣고 있었다(실측 /usr 4.7GB). CUDA 를 쓰는 다른 패키지도 없다
(onnxruntime 은 CPU 빌드). 같은 스택인 genon/preprocessor GPU 빌드는 python:slim(시스템 CUDA 없음)
위에서 정상 동작한다.
⚠️ ubuntu:22.04 까지 낮추지 말 것 — -base 가 포함하는 cuda-compat 이 호스트 드라이버가 CUDA 12.4
보다 구버전일 때 호환성을 메워 준다. 추가 절감(약 250MB) 대비 위험이 크다.

rhwp 빌더 rust:latestrust:1-slim (4개 파일 전부). rust:latest(약 1.5GB)는 buildpack-deps
기반이라 git 이 들어 있지만 slim 에는 없어 git ca-certificates 만 apt 로 추가했다. 산출물이 바이너리
하나뿐이라 최종 이미지 크기는 그대로이고 빌드 중 다운로드/디스크만 줄어든다.
⚠️ genos-rhwp 가 pkg-config/libssl-dev/cmake 같은 시스템 의존을 요구하게 되면 cargo build
깨진다. 그때는 apt 목록에 추가하거나 rust:latest 로 되돌린다.

uv 버전 0.8.0 핀 (4개 파일). 빌드가 --no-install-package / --torch-backend 에 의존하게 됐으니
:latest 로 두면 어느 날 조용히 동작이 바뀔 수 있다.
⚠️ COPY --from=<이미지> 는 ARG 를 확장하지 않는다(FROM 만 확장). 그래서 명명된 스테이지를 둔다:

ARG UV_VERSION=0.8.0          # 첫 FROM 앞에 선언해야 FROM 에서 쓸 수 있다
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv_bin
...
COPY --from=uv_bin /uv /uvx /bin/

부작용 1건: 핀하면서 code-serving 빌드가 깨졌다. base 가 ENV TMPDIR=/app/tmp 를 설정하는데 그 RUN 이
/app/tmp 를 지운 뒤 다시 만들지 않아 error: No such file or directory (os error 2) at path "/app/tmp/.tmpXXXX" 로 죽는다(이전 미핀 uv 는 TMPDIR 을 자동 생성했다). mkdir -p /app/tmp 추가.

code-serving CPU: libspatialindex-devlibspatialindex-c8.
rtree 가 libspatialindex_c.so 를 dlopen 할 때만 필요하므로 런타임 패키지로 충분하다(-dev 는 헤더뿐).
⚠️ 패키지명이 배포판마다 다르다: Debian trixie -c8, Ubuntu 22.04(jammy) -c6(Dockerfile.gpu 가 쓰는 이름).

5) .dockerignore 신설

이 레포에는 Dockerfile 이 9개 있고(루트 ./Dockerfile, .actor/, genon/serving/paddle/,
genon/preprocessor/docker/, build-script/code-serving-doc-parser/) 모두 레포 루트를 컨텍스트로
쓴다.
그래서 whitelist(* 로 전부 막고 !경로 로 되살리기) 대신 blacklist 를 택했다 — whitelist 는
경로 하나만 빠뜨려도 다른 빌드를 조용히 깨뜨린다. 아래 항목이 어떤 Dockerfile 에서도 참조되지 않음을
확인하고 작성했다.

  • 비밀 값 (가장 중요): build-script/hf_private_token.env, **/*.pem, **/*.key.
    .gitignore 로 git 에서는 빠지지만 docker build context 에는 그대로 들어간다. 지금은 어떤
    Dockerfile 도 COPY . . 를 하지 않아 이미지에 실리지 않지만, 누군가 광범위한 COPY 를 추가하는 순간
    토큰이 이미지에 들어간다. (빌드는 --secret 으로 토큰을 주입하므로 컨텍스트에서 빠져도 정상 동작한다.)
  • .git, .venv, __pycache__, *.py[cod], .pytest_cache/.mypy_cache/.ruff_cache,
    *.egg-info, .idea/.vscode/.DS_Store, dist/build/node_modules

변경 파일

파일 내용
.dockerignore 신규 — blacklist 방식, 비밀 값/개인 작업 공간/캐시 제외
genon/preprocessor/docker/Dockerfile.standard 위 1~4 전부
genon/preprocessor/docker/Dockerfile.synap standard 와 동일 변경(주석 문구만 일부 축약)
build-script/code-serving-doc-parser/Dockerfile 위 1~4 + libspatialindex-c8
build-script/code-serving-doc-parser/Dockerfile.gpu 위 1~4 + runtime 베이스 -cudnn-runtime-base
build-script/code-serving-doc-parser/build.config IMAGE_VERSION 0.1.0 → 2.1.4

하위 호환 / 동작 변경

애플리케이션 코드 변경 0건. Dockerfile / .dockerignore / build.config 만 바뀐다.

이미지에서 빠지는 것과 판단 근거:

빠지는 것 왜 안전한가 언제 되돌려야 하나
code_formula 모델 code/formula enrichment 가 기본 off 이고 켜는 코드가 없음 facade 나 서비스 코드가 enrichment 를 노출/활성화할 때
doc_parser_models 의 docling-models / layout-old 참조 0건, 기본 layout 은 ds4sd--docling-layout-old MNCAI_CUSTOM_LAYOUT 경로를 실제로 쓰게 될 때
tessedata.tar.gz 참조 0건, 한국어 tessdata 는 apt 로 이미 존재
torch/test, torch/include 추론 경로 미사용 torch.utils.cpp_extension(JIT C++ 확장)을 쓰는 코드가 붙을 때
opencv-python(non-headless) 첫 파티 import cv2 0건, GUI 불필요 GUI 렌더링이 필요해질 때
dev 의존성 그룹 런타임 불필요 이미지 안에서 pytest 를 돌려야 할 때
시스템 CUDA/cuDNN (GPU) torch 가 pip nvidia 휠에 링크 시스템 CUDA 를 직접 링크하는 패키지를 추가할 때

코드서빙 특유의 리스크: 이 이미지는 런타임에 서비스 코드를 git clone 해서 실행한다. 그 외부 코드가
torch.utils.cpp_extension 을 쓰면 torch/include 부재로 실패한다. 현재 이 레포에는 사용처가 없지만
서비스 코드는 이미지 밖에서 오므로 보장할 수 없다 — 그런 서비스를 붙이려면 해당 RUN 에서 include
제거를 빼야 한다.

Summary by CodeRabbit

  • Enhancements
    • Updated the document-parsing service image to version 2.1.4.
    • Improved CPU and GPU deployment support with more consistent dependency and hardware configuration.
    • Reduced container size by removing unused libraries, models, and assets.
    • Improved container file ownership and runtime permissions for more reliable deployments.
    • Limited downloaded document-processing models to those required by the service.
  • Security
    • Added container build exclusions for secrets, local environments, metadata, caches, and personal workspace files.

@inoray inoray self-assigned this Aug 7, 2026
@inoray inoray linked an issue Aug 7, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request updates Docker build context exclusions and four image definitions. It pins build tools, narrows dependencies and model downloads, standardizes headless OpenCV, reduces copied assets, and applies targeted runtime ownership changes.

Changes

Container build updates

Layer / File(s) Summary
Build context and release metadata
.dockerignore, build-script/code-serving-doc-parser/build.config
The build context excludes secrets, metadata, caches, workspace files, and build artifacts. The parser image version changes to 2.1.4.
CPU document-parser image
build-script/code-serving-doc-parser/Dockerfile
The image pins uv, installs CPU dependencies, removes unused GPU and Torch assets, validates headless OpenCV, narrows model downloads, uses a slim Rust builder, and preserves ownership during copies.
GPU document-parser image
build-script/code-serving-doc-parser/Dockerfile.gpu
The image installs CUDA dependencies through uv, uses a smaller CUDA base, narrows model downloads, validates OpenCV, binds only the required font archive, and applies targeted ownership fixes.
Standard preprocessor image
genon/preprocessor/docker/Dockerfile.standard
The image filters CPU dependencies, pins build tools, narrows model and font inputs, corrects EasyOCR extraction, validates OpenCV, and replaces recursive ownership changes.
Synap preprocessor image
genon/preprocessor/docker/Dockerfile.synap
The image applies pinned tooling, CPU/GPU dependency filtering, selected model downloads, corrected EasyOCR extraction, slim builders, and ownership-preserving runtime copies.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: heechankim-genon, seongmincho315

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the Docker image size optimization work described in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/342-docker-image-size

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
genon/preprocessor/docker/Dockerfile.standard (2)

232-235: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

CPU Torch versions are hard-coded while uv sync no longer installs Torch. Both images now skip Torch during uv sync, so this pin is the single source of the installed version. The OpenCV block in the same files reads its version from uv.lock for exactly this reason.

  • genon/preprocessor/docker/Dockerfile.standard#L232-L235: read the torch and torchvision versions from uv.lock and use them in the uv pip install command.
  • genon/preprocessor/docker/Dockerfile.synap#L236-L239: apply the same lockfile-derived pin.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@genon/preprocessor/docker/Dockerfile.standard` around lines 232 - 235, Update
the CPU Torch install blocks in genon/preprocessor/docker/Dockerfile.standard
lines 232-235 and genon/preprocessor/docker/Dockerfile.synap lines 236-239 to
derive the torch and torchvision versions from uv.lock, matching the existing
OpenCV lockfile-version pattern, and pass those values to uv pip install instead
of hard-coded pins.

551-555: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The new ownership fix adds a second hard-coded python3.12 path in both images. ARG PY_VER=3.12.12 controls the interpreter version, so a version bump breaks the symlink line and the new chown -h line.

  • genon/preprocessor/docker/Dockerfile.standard#L551-L555: replace the literal path with ${APP_VENV}/lib/python3*/site-packages/hwp_sdk.
  • genon/preprocessor/docker/Dockerfile.synap#L574-L578: apply the same glob-based path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@genon/preprocessor/docker/Dockerfile.standard` around lines 551 - 555,
Replace the hard-coded python3.12 hwp_sdk ownership path in the
Dockerfile.standard RUN ownership block with the
`${APP_VENV}/lib/python3*/site-packages/hwp_sdk` glob. Apply the same change in
Dockerfile.synap at lines 574-578; no other ownership behavior should change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@build-script/code-serving-doc-parser/Dockerfile`:
- Around line 135-139: Replace the source-based uv pip install in
build-script/code-serving-doc-parser/Dockerfile at lines 135-139 with
installation from the exported, frozen CPU dependency artifact, preserving
CPU-compatible Torch. Apply the corresponding change in
build-script/code-serving-doc-parser/Dockerfile.gpu at lines 79-82 to install
the fully pinned CUDA 12.4 artifact and retain CUDA-compatible Torch; both
variants must stop resolving pyproject.toml dependency ranges during the build.

In `@genon/preprocessor/docker/Dockerfile.standard`:
- Around line 447-453: The EasyOCR cache download can retain an HTTP error body
as a valid model archive. In the EasyOCR download blocks of
genon/preprocessor/docker/Dockerfile.standard lines 447-453 and
genon/preprocessor/docker/Dockerfile.synap lines 471-477, make curl fail on HTTP
errors, download to korean_g2.zip.tmp, and move the temporary file to
korean_g2.zip only after a successful download.

---

Nitpick comments:
In `@genon/preprocessor/docker/Dockerfile.standard`:
- Around line 232-235: Update the CPU Torch install blocks in
genon/preprocessor/docker/Dockerfile.standard lines 232-235 and
genon/preprocessor/docker/Dockerfile.synap lines 236-239 to derive the torch and
torchvision versions from uv.lock, matching the existing OpenCV lockfile-version
pattern, and pass those values to uv pip install instead of hard-coded pins.
- Around line 551-555: Replace the hard-coded python3.12 hwp_sdk ownership path
in the Dockerfile.standard RUN ownership block with the
`${APP_VENV}/lib/python3*/site-packages/hwp_sdk` glob. Apply the same change in
Dockerfile.synap at lines 574-578; no other ownership behavior should change.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 48fac937-2918-4bf5-866c-77ddd1da0c86

📥 Commits

Reviewing files that changed from the base of the PR and between a5e8b62 and 521b62a.

📒 Files selected for processing (6)
  • .dockerignore
  • build-script/code-serving-doc-parser/Dockerfile
  • build-script/code-serving-doc-parser/Dockerfile.gpu
  • build-script/code-serving-doc-parser/build.config
  • genon/preprocessor/docker/Dockerfile.standard
  • genon/preprocessor/docker/Dockerfile.synap

Comment on lines 135 to +139
RUN --mount=type=cache,target=/root/.cache/uv \
rm -rf /app/tmp /app/nltk_data && \
mkdir -p /app/tmp && \
uv venv --seed && \
uv pip install .
uv pip install . --torch-backend=cpu

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect whether either Dockerfile installs a frozen/exported dependency artifact.
rg -n -C 3 \
  'uv (pip )?(install|sync)|uv (lock|export)|torch-backend|uv\.lock' \
  build-script/code-serving-doc-parser/Dockerfile \
  build-script/code-serving-doc-parser/Dockerfile.gpu \
  build-script/code-serving-doc-parser/pyproject.toml

# Inspect direct dependency constraints. Any range here is resolved anew by `uv pip install .`.
sed -n '/^\[project\]/,/^\[/p' build-script/code-serving-doc-parser/pyproject.toml

Repository: genonai/doc_parser

Length of output: 19539


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- uv.lock package pins for variants/opencv/torch candidates ---'
python3 - <<'PY'
from pathlib import Path
p = Path('build-script/code-serving-doc-parser/uv.lock')
data = p.read_text()
for needle in ['opencv-python', 'opencv-python-headless', 'torch', 'numpy', 'pandas', 'transformers']:
    print(f'[{needle}]')
    # Print package blocks that mention the needle in name or first-version line nearby.
    lines = data.splitlines()
    in_block = False
    block_lines = []
    name = None
    version = None
    for i,line in enumerate(lines):
        stripped=line.strip()
        if stripped.startswith('[[package]]'):
            if name and name.find(needle) != -1:
                print('\n'.join(block_lines))
            in_block = True
            name = version = None
            block_lines = []
        elif in_block:
            block_lines.append(line)
            if stripped.startswith('name = '):
                name = stripped.split('"',2)[1].strip('"')
            if stripped.startswith('version = '):
                version = stripped.split('"',2)[1].strip('"')
    if name and name.find(needle) != -1:
        print('\n'.join(block_lines))
PY

printf '%s\n' '--- resolved dependency ranges in pyproject.toml ---'
python3 - <<'PY'
from pathlib import Path
p = Path('build-script/code-serving-doc-parser/pyproject.toml')
lines = p.read_text().splitlines()
in_project = False
for line in lines:
    if line.strip() == '[project]':
        in_project = True
    elif in_project and line.startswith('['):
        break
    elif in_project and line.startswith('    "') and '==' not in line:
        print(line)
PY

printf '%s\n' '--- uv command docs availability for sync/link-file check ---'
uv --version 2>/dev/null || true
uv pip install --help 2>/dev/null | sed -n '1,140p' || true
uv sync --help 2>/dev/null | sed -n '1,140p' || true

Repository: genonai/doc_parser

Length of output: 50374


Install from a variant-specific frozen dependency artifact.

uv pip install . resolves pyproject.toml ranges again; it does not consume the copied uv.lock. Dependency versions can drift between builds for both fastapi>=0.115.12/opencv-python>=4.11.0.86 and other ranges. Use the exported CPU artifact for the CPU image and a fully pinned CUDA 12.4 artifact for the GPU image, keeping Torch compatible with the selected variant.

📍 Affects 2 files
  • build-script/code-serving-doc-parser/Dockerfile#L135-L139 (this comment)
  • build-script/code-serving-doc-parser/Dockerfile.gpu#L79-L82
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build-script/code-serving-doc-parser/Dockerfile` around lines 135 - 139,
Replace the source-based uv pip install in
build-script/code-serving-doc-parser/Dockerfile at lines 135-139 with
installation from the exported, frozen CPU dependency artifact, preserving
CPU-compatible Torch. Apply the corresponding change in
build-script/code-serving-doc-parser/Dockerfile.gpu at lines 79-82 to install
the fully pinned CUDA 12.4 artifact and retain CUDA-compatible Torch; both
variants must stop resolving pyproject.toml dependency ranges during the build.

Comment on lines 447 to +453
RUN --mount=type=cache,target=/root/.cache/easyocr_korean \
echo "EasyOCR ver: ${EASYOCR_VER}"; \
mkdir -p /models/EasyOcr && \
if [ ! -f /models/EasyOcr/korean_g2.zip ]; then \
if [ ! -f /root/.cache/easyocr_korean/korean_g2.zip ]; then \
curl -L -o /root/.cache/easyocr_korean/korean_g2.zip "https://github.com/JaidedAI/EasyOCR/releases/download/v1.3/korean_g2.zip"; \
unzip -q -o /root/.cache/easyocr_korean/korean_g2.zip -d /models/EasyOcr; \
fi
fi; \
unzip -q -o /root/.cache/easyocr_korean/korean_g2.zip -d /models/EasyOcr

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Cached EasyOCR download can poison the shared cache mount in both preprocessor images. curl -L -o writes the HTTP error body to korean_g2.zip and exits 0. The changed condition now checks the cache path, so a corrupt file is treated as valid on every later build and is never replaced.

  • genon/preprocessor/docker/Dockerfile.standard#L447-L453: add --fail to curl, download to korean_g2.zip.tmp, then mv it into the cache.
  • genon/preprocessor/docker/Dockerfile.synap#L471-L477: apply the same --fail and temporary-file pattern.
📍 Affects 2 files
  • genon/preprocessor/docker/Dockerfile.standard#L447-L453 (this comment)
  • genon/preprocessor/docker/Dockerfile.synap#L471-L477
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@genon/preprocessor/docker/Dockerfile.standard` around lines 447 - 453, The
EasyOCR cache download can retain an HTTP error body as a valid model archive.
In the EasyOCR download blocks of genon/preprocessor/docker/Dockerfile.standard
lines 447-453 and genon/preprocessor/docker/Dockerfile.synap lines 471-477, make
curl fail on HTTP errors, download to korean_g2.zip.tmp, and move the temporary
file to korean_g2.zip only after a successful download.

@inoray
inoray requested a review from HeechanKim-Genon August 7, 2026 08:12
@HeechanKim-Genon
HeechanKim-Genon merged commit 996b207 into develop Aug 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

도커이미지 용량 최적화

2 participants