image: ship a C compiler, or vLLM never starts (v0.2.62)

Why a remote host was sending PaddleOCR requests: surya never ran. Every attempt
ended as

  [ocr] engine 'surya' could not serve (vLLM exited (code 1) before becoming
  ready) … falling back to paddle -> doctr

and the root cause, four frames down in the vLLM subprocess output:

  RuntimeError: Failed to find C compiler. Please specify via CC environment
  variable or set triton.knobs.build.impl.

Triton JIT-compiles its CUDA driver module at RUNTIME, on first engine start. The
image has no cc, gcc or clang — confirmed by looking inside it; the single dpkg
match is gcc-*-base, runtime libs, not a compiler. So gcc and libc6-dev are now
installed in the shipped stage, with the reason recorded beside them: a compiler
in a runtime image looks like an obvious thing to delete.

This affects EVERY vLLM engine, not just OCR.

What made it invisible: the OCR fallback chain worked. All 203 /v1/ocr requests in
the window returned 200 — on paddle, 218 times, after surya failed. Nothing in the
HTTP log said anything was wrong, and the only outward sign was a remote host
preferring an engine it should not have needed.

The RunPod vLLM capability profile has carried gcc from the start. The main image
never did. The test checks both so they cannot drift apart again.

Needs a rebuild to take effect — a compiler cannot be bind-mounted in like the
Python fixes.

4 tests.
Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182DhR1eFNPQyGmDrpHbedY
parent 5188ee6b
......@@ -16,7 +16,7 @@
# Canonical product version for CoderAI — single source of truth. Both the API
# metadata and the admin web UI read from here.
__version__ = "0.2.61"
__version__ = "0.2.62"
__tagline__ = "Complete orchestration, distribution and escalation of remotizable advanced inference."
# Configure the CUDA caching allocator BEFORE torch is imported anywhere.
......
......@@ -158,9 +158,18 @@ ENV DEBIAN_FRONTEND=noninteractive \
CODERAI_HOST=0.0.0.0 \
CODERAI_PORT=8776
# gcc + libc6-dev are NOT for building this image: Triton (under vLLM) JIT-compiles
# its CUDA driver module at RUNTIME, on the first engine start. Without a C compiler
# it dies with
# RuntimeError: Failed to find C compiler. Please specify via CC environment
# variable or set triton.knobs.build.impl.
# which surfaces as "vLLM exited (code 1) before becoming ready" — so every vLLM
# engine, surya OCR included, silently fell back to another engine.
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
ffmpeg \
gcc \
libc6-dev \
git \
libgomp1 \
libgl1 \
......
"""The runtime image must carry a C compiler, for Triton.
Not a build-time dependency — a RUNTIME one. Triton (under vLLM) JIT-compiles its
CUDA driver module on the first engine start:
RuntimeError: Failed to find C compiler. Please specify via CC environment
variable or set triton.knobs.build.impl.
which the engine manager sees only as "vLLM exited (code 1) before becoming
ready". Every vLLM engine then falls back to another one, and because the OCR
fallback chain works, the requests still return 200 — so surya was never used and
nothing looked broken. A remote host sending PaddleOCR requests was the only
visible symptom.
The RunPod vLLM capability profile had gcc from the start; the main image did not.
This keeps the two from drifting again.
"""
import pathlib
import re
ROOT = pathlib.Path(__file__).resolve().parents[1]
DOCKERFILE = ROOT / "packaging" / "linux" / "Dockerfile.oci"
RUNPOD_VLLM_APT = ROOT / "packaging" / "runpod" / "profiles" / "vllm.apt"
def _runtime_stage(text: str) -> str:
"""Everything from the last FROM onwards — the stage that actually ships."""
starts = [m.start() for m in re.finditer(r"^FROM ", text, re.M)]
return text[starts[-1]:] if starts else text
def test_the_shipped_stage_installs_a_c_compiler():
stage = _runtime_stage(DOCKERFILE.read_text(encoding="utf-8"))
assert re.search(r"^\s+gcc\s*\\?\s*$", stage, re.M), \
"no gcc in the runtime stage — Triton cannot build its driver module"
def test_it_also_has_the_headers_the_compile_needs():
stage = _runtime_stage(DOCKERFILE.read_text(encoding="utf-8"))
assert re.search(r"^\s+libc6-dev\s*\\?\s*$", stage, re.M), \
"gcc without libc6-dev cannot compile driver.c"
def test_the_reason_is_recorded_next_to_it():
"""A later cleanup would otherwise drop a compiler from a runtime image as
obviously unnecessary."""
text = DOCKERFILE.read_text(encoding="utf-8")
assert "Triton" in text and "runtime" in text.lower()
assert "Failed to find C compiler" in text
def test_the_runpod_vllm_profile_agrees():
"""Both places run vLLM; both need the compiler."""
if not RUNPOD_VLLM_APT.is_file():
return
pkgs = [l.strip() for l in RUNPOD_VLLM_APT.read_text(encoding="utf-8").splitlines()
if l.strip() and not l.strip().startswith("#")]
assert "gcc" in pkgs
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment