Feature/342 docker image size - #344
Conversation
📝 WalkthroughWalkthroughThe 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. ChangesContainer build updates
Estimated code review effort: 4 (Complex) | ~45 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
genon/preprocessor/docker/Dockerfile.standard (2)
232-235: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winCPU Torch versions are hard-coded while
uv syncno longer installs Torch. Both images now skip Torch duringuv sync, so this pin is the single source of the installed version. The OpenCV block in the same files reads its version fromuv.lockfor exactly this reason.
genon/preprocessor/docker/Dockerfile.standard#L232-L235: read thetorchandtorchvisionversions fromuv.lockand use them in theuv pip installcommand.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 valueThe new ownership fix adds a second hard-coded
python3.12path in both images.ARG PY_VER=3.12.12controls the interpreter version, so a version bump breaks the symlink line and the newchown -hline.
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
📒 Files selected for processing (6)
.dockerignorebuild-script/code-serving-doc-parser/Dockerfilebuild-script/code-serving-doc-parser/Dockerfile.gpubuild-script/code-serving-doc-parser/build.configgenon/preprocessor/docker/Dockerfile.standardgenon/preprocessor/docker/Dockerfile.synap
| 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 |
There was a problem hiding this comment.
🗄️ 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.tomlRepository: 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' || trueRepository: 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.
| 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 |
There was a problem hiding this comment.
🩺 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--failtocurl, download tokorean_g2.zip.tmp, thenmvit into the cache.genon/preprocessor/docker/Dockerfile.synap#L471-L477: apply the same--failand 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.
feat(#342): 도커 이미지 용량 최적화 — 4개 Dockerfile 공통 정비 +
.dockerignore신설개요
전처리기/코드서빙 도커 이미지가 필요 이상으로 커진 원인을 찾아 제거한다. 대상은 이 레포의
빌드 대상 Dockerfile 4개 전부이며, 애플리케이션 코드는 한 줄도 바뀌지 않는다.
genon/preprocessor/docker/Dockerfile.standardgenon/preprocessor/docker/Dockerfile.synapbuild-script/code-serving-doc-parser/Dockerfilebuild-script/code-serving-doc-parser/Dockerfile.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 의
⚠️ cache mount 가 없는 RUN(rhwp 빌더 등)의
rm -rf /var/lib/apt/lists/*제거./var/cache/apt와/var/lib/apt/lists를 cache mount 로 잡은 RUN 은 애초에 그 내용이 이미지레이어에 포함되지 않는다. 크기 이득은 0이면서 다음 빌드가 재사용할 apt 인덱스만 파괴하고 있었다.
rm은 실제로 레이어를 줄이므로 그대로 유지했다.2) 모델 자산 선별
docling-tools models download목록 명시. 인자 없이 호출하면 기본 세트를 전부 받는다.code_formula(ds4sd--CodeFormula, 506MB).do_code_enrichment/do_formula_enrichment가pipeline_options.py에서 기본False이고 이를 켜는 config 키·코드가없어
CodeFormulaModel은enabled=False로만 생성된다.향후 facade 가 이를 노출하거나 코드서빙에서 런타임 clone 되는 서비스 코드가 켜면
오프라인 환경에서 모델이 없어 실패한다. 그때는 목록에 다시 넣어야 한다.
docling/utils/model_downloader.py의with_*플래그와 1:1):layout→ PDF 는genos_layout(dotsocr)을 쓰지만 PPT/PPTX 경량 파이프라인이 barePdfPipelineOptions()로LayoutModel을 만들어 실제 로드한다tableformer→layout_model_type: docling_layout배포에서 필요picture_classifier→chart.enableopt-in (16MB)easyocr→ CRAFT 검출기(craft_mlt_25k83MB) 등. 목록에서 빼면 아래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_modelsEasyOCR 한국어 모델 캐시 조건 수정 (버그). 조건이
/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 /models와HF_HOME을 쓴다 — 실제로 그 캐시는 4KB로 비어 있었다).3) venv 다이어트
uv sync --no-dev(전처리기 2개 파일) — dev 그룹(pytest/mypy/debugpy/ipykernel/pre-commit …)은런타임 이미지에 불필요하다. 붙이지 않으면 uv 가 기본 설치해 약 100MB(debugpy 18M, mypy+mypyc
.so47M 등)가 들어온다. 코드서빙은
uv pip install .방식이라 애초에 dev 그룹을 설치하지 않는다.CPU/GPU 휠을 처음부터 올바르게 받는다. 도구별로 방법이 다르다:
Dockerfile.standard/.synapuv sync에는--torch-backend가 없어 →uv.lock에서 뽑은--no-install-package nvidia-… triton+ torch/torchvision 제외 후, CPU 휠 재설치uv pip install . --torch-backend=cpuuv pip install . --torch-backend=cu124(재설치 단계 삭제)standard 쪽 제외 목록도 하드코딩하지 않고
uv.lock에서 추출한다:🔴 하드코딩된 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; } || truetorch 런타임 미사용 자산 제거 — 약 141MB (
⚠️
torch/test81M +torch/include60M).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 를--reinstalluv 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.04→12.4.1-base-ubuntu22.04.torch 는 pip nvidia 휠(uv.lock 에 15개, cuDNN 포함)에 링크되므로 베이스가 주는 시스템 CUDA/cuDNN 은
쓰이지 않는다 — CUDA 를 사실상 두 번 싣고 있었다(실측
/usr4.7GB). CUDA 를 쓰는 다른 패키지도 없다(onnxruntime 은 CPU 빌드). 같은 스택인
genon/preprocessorGPU 빌드는python:slim(시스템 CUDA 없음)위에서 정상 동작한다.
ubuntu:22.04까지 낮추지 말 것 —-base가 포함하는cuda-compat이 호스트 드라이버가 CUDA 12.4보다 구버전일 때 호환성을 메워 준다. 추가 절감(약 250MB) 대비 위험이 크다.
rhwp 빌더
⚠️ genos-rhwp 가
rust:latest→rust:1-slim(4개 파일 전부).rust:latest(약 1.5GB)는 buildpack-deps기반이라 git 이 들어 있지만 slim 에는 없어
git ca-certificates만 apt 로 추가했다. 산출물이 바이너리하나뿐이라 최종 이미지 크기는 그대로이고 빌드 중 다운로드/디스크만 줄어든다.
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 만 확장). 그래서 명명된 스테이지를 둔다:부작용 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:
⚠️ 패키지명이 배포판마다 다르다: Debian trixie
libspatialindex-dev→libspatialindex-c8.rtree 가
libspatialindex_c.so를 dlopen 할 때만 필요하므로 런타임 패키지로 충분하다(-dev 는 헤더뿐).-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변경 파일
.dockerignoregenon/preprocessor/docker/Dockerfile.standardgenon/preprocessor/docker/Dockerfile.synapbuild-script/code-serving-doc-parser/Dockerfilelibspatialindex-c8build-script/code-serving-doc-parser/Dockerfile.gpu-cudnn-runtime→-basebuild-script/code-serving-doc-parser/build.configIMAGE_VERSION0.1.0 → 2.1.4하위 호환 / 동작 변경
애플리케이션 코드 변경 0건. Dockerfile /
.dockerignore/build.config만 바뀐다.이미지에서 빠지는 것과 판단 근거:
code_formula모델doc_parser_models의 docling-models / layout-oldds4sd--docling-layout-oldMNCAI_CUSTOM_LAYOUT경로를 실제로 쓰게 될 때tessedata.tar.gztorch/test,torch/includetorch.utils.cpp_extension(JIT C++ 확장)을 쓰는 코드가 붙을 때opencv-python(non-headless)import cv20건, GUI 불필요코드서빙 특유의 리스크: 이 이미지는 런타임에 서비스 코드를
git clone해서 실행한다. 그 외부 코드가torch.utils.cpp_extension을 쓰면torch/include부재로 실패한다. 현재 이 레포에는 사용처가 없지만서비스 코드는 이미지 밖에서 오므로 보장할 수 없다 — 그런 서비스를 붙이려면 해당
RUN에서 include제거를 빼야 한다.
Summary by CodeRabbit