Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
39599b6
refactor: replace install-common.sh with declarative artifact system
eoinfennessy Jun 30, 2026
29cadd3
fix: place HF cache under APP_ROOT and export HF_HOME
eoinfennessy Jun 30, 2026
f5b3ca3
fix: add path traversal validation and pin script dependencies
eoinfennessy Jun 30, 2026
f6ed9d2
fix: derive tiktoken cache key from URL instead of hardcoding
eoinfennessy Jun 30, 2026
fc46665
fix: swap opencv-python for headless variant via post-install step
eoinfennessy Jul 1, 2026
e57ab0f
fix: pin opencv-python-headless to the resolved opencv-python version
eoinfennessy Jul 1, 2026
5e922b5
refactor: use artifact filenames as destination paths to simplify cop…
eoinfennessy Jul 1, 2026
091f69b
fix: remove unnecessary chown/chmod on read-only docling models dir
eoinfennessy Jul 1, 2026
e7825d4
fix: remove vestigial .ogx mkdir from copy-artifacts.sh
eoinfennessy Jul 1, 2026
21f0b48
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 2, 2026
2927762
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 2, 2026
ecc5cc4
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 2, 2026
6133b80
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 2, 2026
5338b47
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 3, 2026
2384d33
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 6, 2026
7ddebde
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 6, 2026
8a09237
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 6, 2026
df90b8c
Merge branch 'main' into unify-install-scripts
mergify[bot] Jul 6, 2026
b19cf51
increase download timeout to 3 minutes
eoinfennessy Jul 7, 2026
406c25a
ensure OPENCV_VERSION variable is set after extraction
eoinfennessy Jul 7, 2026
eecbac6
cache artifact downloads across container builds
eoinfennessy Jul 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,24 @@ ENV UV_INDEX_STRATEGY=unsafe-best-match

COPY distribution/constraints.txt ${APP_ROOT}/constraints.txt
COPY distribution/requirements.txt ${APP_ROOT}/requirements.txt
RUN uv pip install --constraint ${APP_ROOT}/constraints.txt -r ${APP_ROOT}/requirements.txt

COPY --chmod=755 distribution/install-common.sh ${APP_ROOT}/install-common.sh
# Package docling transitively pulls in opencv-python via rapidocr.
# opencv-python requires libGL.so.1 (absent in UBI). Swap it for the headless
# variant after install, pinned to the exact version the resolver chose.
RUN uv pip install --constraint ${APP_ROOT}/constraints.txt -r ${APP_ROOT}/requirements.txt \
&& OPENCV_VERSION=$(uv pip show opencv-python 2>/dev/null | awk '/^Version:/{print $2}') \
&& [ -n "${OPENCV_VERSION}" ] || { echo "ERROR: opencv-python not found after install"; exit 1; } \
&& uv pip uninstall opencv-python \
&& uv pip install --constraint ${APP_ROOT}/constraints.txt "opencv-python-headless==${OPENCV_VERSION}"
Comment thread
eoinfennessy marked this conversation as resolved.

COPY distribution/fetch_artifacts.py ${APP_ROOT}/fetch_artifacts.py
COPY --chmod=755 distribution/copy-artifacts.sh ${APP_ROOT}/copy-artifacts.sh
COPY distribution/artifacts.lock.yaml ${APP_ROOT}/artifacts.lock.yaml
RUN --mount=type=cache,target=/var/cache/artifacts,uid=1001,gid=0 \
uv run ${APP_ROOT}/fetch_artifacts.py ${APP_ROOT}/artifacts.lock.yaml /var/cache/artifacts \
&& ${APP_ROOT}/copy-artifacts.sh /var/cache/artifacts
ENV DOCLING_ARTIFACTS_PATH="${APP_ROOT}/.cache/docling/models"
RUN ${APP_ROOT}/install-common.sh
ENV HF_HOME="${APP_ROOT}/.cache/huggingface"
ENV TIKTOKEN_CACHE_DIR="${APP_ROOT}/.cache/tiktoken"

LABEL com.ogx.config.config.yaml="IyBUaGlzIGZpbGUgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgZnJvbSBidWlsZC55YW1sCiMgYnkgYnVpbGQvYnVpbGQucHkgLSBkbyBub3QgZWRpdCBtYW51YWxseS4KIwojIFN0cmlwcGVkIHByb3ZpZGVyIHR5cGVzIChkZXBlbmRlbmN5IG9ubHkgLSBhdmFpbGFibGUgdmlhIGN1c3RvbSBjb25maWcueWFtbCk6CiMgICAtIGlubGluZTo6ZG9jbGluZwojICAgLSBpbmxpbmU6OmZhaXNzCiMgICAtIGlubGluZTo6bWFya2l0ZG93bgojICAgLSBpbmxpbmU6Om1pbHZ1cwojICAgLSBpbmxpbmU6OnB5cGRmCiMgICAtIGlubGluZTo6c2VudGVuY2UtdHJhbnNmb3JtZXJzCiMgICAtIHJlbW90ZTo6ZG9jbGluZy1zZXJ2ZQp2ZXJzaW9uOiAyCmltYWdlX25hbWU6IHJoCmFwaXM6CiAgLSByZXNwb25zZXMKICAtIG1lc3NhZ2VzCiAgLSBiYXRjaGVzCiAgLSBpbmZlcmVuY2UKICAtIHRvb2xfcnVudGltZQogIC0gdmVjdG9yX2lvCiAgLSBmaWxlcwogIC0gZmlsZV9wcm9jZXNzb3JzCnByb3ZpZGVyczoKICBpbmZlcmVuY2U6CiAgICAtIHByb3ZpZGVyX2lkOiAke2Vudi5WTExNX1VSTDordmxsbS1pbmZlcmVuY2V9CiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6dmxsbQogICAgICBjb25maWc6CiAgICAgICAgYmFzZV91cmw6ICR7ZW52LlZMTE1fVVJMOj19CiAgICAgICAgbWF4X3Rva2VuczogJHtlbnYuVkxMTV9NQVhfVE9LRU5TOj00MDk2fQogICAgICAgIGFwaV90b2tlbjogJHtlbnYuVkxMTV9BUElfVE9LRU46PWZha2V9CiAgICAgICAgdGxzX3ZlcmlmeTogJHtlbnYuVkxMTV9UTFNfVkVSSUZZOj10cnVlfQogICAgICAgIHJlZnJlc2hfbW9kZWxzOiAke2Vudi5WTExNX1JFRlJFU0hfTU9ERUxTOj1mYWxzZX0KICAgIC0gcHJvdmlkZXJfaWQ6ICR7ZW52LlZMTE1fRU1CRURESU5HX1VSTDordmxsbS1lbWJlZGRpbmd9CiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6dmxsbQogICAgICBjb25maWc6CiAgICAgICAgYmFzZV91cmw6ICR7ZW52LlZMTE1fRU1CRURESU5HX1VSTDo9fQogICAgICAgIG1heF90b2tlbnM6ICR7ZW52LlZMTE1fRU1CRURESU5HX01BWF9UT0tFTlM6PTQwOTZ9CiAgICAgICAgYXBpX3Rva2VuOiAke2Vudi5WTExNX0VNQkVERElOR19BUElfVE9LRU46PWZha2V9CiAgICAgICAgdGxzX3ZlcmlmeTogJHtlbnYuVkxMTV9FTUJFRERJTkdfVExTX1ZFUklGWTo9dHJ1ZX0KICAgICAgICByZWZyZXNoX21vZGVsczogJHtlbnYuVkxMTV9FTUJFRERJTkdfUkVGUkVTSF9NT0RFTFM6PWZhbHNlfQogICAgLSBwcm92aWRlcl9pZDogJHtlbnYuRU5BQkxFX0JFRFJPQ0s6K2JlZHJvY2t9CiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6YmVkcm9jawogICAgICBjb25maWc6CiAgICAgICAgYXdzX2JlZHJvY2tfYmVhcmVyX3Rva2VuOiAke2Vudi5BV1NfQkVEUk9DS19CRUFSRVJfVE9LRU46PX0KICAgICAgICByZWdpb25fbmFtZTogJHtlbnYuQVdTX0RFRkFVTFRfUkVHSU9OOj11cy1lYXN0LTJ9CiAgICAgICAgYXdzX3JvbGVfYXJuOiAke2Vudi5BV1NfUk9MRV9BUk46PX0KICAgICAgICBhd3Nfd2ViX2lkZW50aXR5X3Rva2VuX2ZpbGU6ICR7ZW52LkFXU19XRUJfSURFTlRJVFlfVE9LRU5fRklMRTo9fQogICAgLSBwcm92aWRlcl9pZDogJHtlbnYuV0FUU09OWF9BUElfS0VZOit3YXRzb254fQogICAgICBwcm92aWRlcl90eXBlOiByZW1vdGU6OndhdHNvbngKICAgICAgY29uZmlnOgogICAgICAgIGJhc2VfdXJsOiAke2Vudi5XQVRTT05YX0JBU0VfVVJMOj1odHRwczovL3VzLXNvdXRoLm1sLmNsb3VkLmlibS5jb219CiAgICAgICAgYXBpX2tleTogJHtlbnYuV0FUU09OWF9BUElfS0VZOj19CiAgICAgICAgcHJvamVjdF9pZDogJHtlbnYuV0FUU09OWF9QUk9KRUNUX0lEOj19CiAgICAtIHByb3ZpZGVyX2lkOiAke2Vudi5BWlVSRV9BUElfS0VZOithenVyZX0KICAgICAgcHJvdmlkZXJfdHlwZTogcmVtb3RlOjphenVyZQogICAgICBjb25maWc6CiAgICAgICAgYXBpX2tleTogJHtlbnYuQVpVUkVfQVBJX0tFWTo9fQogICAgICAgIGFwaV9iYXNlOiAke2Vudi5BWlVSRV9BUElfQkFTRTo9fQogICAgICAgIGFwaV92ZXJzaW9uOiAke2Vudi5BWlVSRV9BUElfVkVSU0lPTjo9fQogICAgICAgIGFwaV90eXBlOiAke2Vudi5BWlVSRV9BUElfVFlQRTo9fQogICAgLSBwcm92aWRlcl9pZDogJHtlbnYuVkVSVEVYX0FJX1BST0pFQ1Q6K3ZlcnRleGFpfQogICAgICBwcm92aWRlcl90eXBlOiByZW1vdGU6OnZlcnRleGFpCiAgICAgIGNvbmZpZzoKICAgICAgICBwcm9qZWN0OiAke2Vudi5WRVJURVhfQUlfUFJPSkVDVDo9fQogICAgICAgIGxvY2F0aW9uOiAke2Vudi5WRVJURVhfQUlfTE9DQVRJT046PWdsb2JhbH0KICAgIC0gcHJvdmlkZXJfaWQ6ICR7ZW52Lk9QRU5BSV9BUElfS0VZOitvcGVuYWl9CiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6b3BlbmFpCiAgICAgIGNvbmZpZzoKICAgICAgICBhcGlfa2V5OiAke2Vudi5PUEVOQUlfQVBJX0tFWTo9fQogICAgICAgIGJhc2VfdXJsOiAke2Vudi5PUEVOQUlfQkFTRV9VUkw6PWh0dHBzOi8vYXBpLm9wZW5haS5jb20vdjF9CiAgICAtIHByb3ZpZGVyX2lkOiAke2Vudi5FTkFCTEVfR0VNSU5JOitnZW1pbml9CiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6Z2VtaW5pCiAgICAgIGNvbmZpZzoKICAgICAgICBhcGlfa2V5OiAke2Vudi5HRU1JTklfQVBJX0tFWTo9fQogICAgICAgIGFjY2Vzc190b2tlbjogJHtlbnYuR0VNSU5JX0FDQ0VTU19UT0tFTjo9fQogICAgICAgIHByb2plY3Q6ICR7ZW52LkdFTUlOSV9BSV9QUk9KRUNUOj19CiAgICAtIHByb3ZpZGVyX2lkOiAke2Vudi5BTlRIUk9QSUNfQVBJX0tFWTorYW50aHJvcGljfQogICAgICBwcm92aWRlcl90eXBlOiByZW1vdGU6OmFudGhyb3BpYwogICAgICBjb25maWc6CiAgICAgICAgYXBpX2tleTogJHtlbnYuQU5USFJPUElDX0FQSV9LRVk6PX0KICB2ZWN0b3JfaW86CiAgICAtIHByb3ZpZGVyX2lkOiAke2Vudi5NSUxWVVNfRU5EUE9JTlQ6K21pbHZ1cy1yZW1vdGV9CiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6bWlsdnVzCiAgICAgIGNvbmZpZzoKICAgICAgICB1cmk6ICR7ZW52Lk1JTFZVU19FTkRQT0lOVDo9fQogICAgICAgIHRva2VuOiAke2Vudi5NSUxWVVNfVE9LRU46PX0KICAgICAgICBzZWN1cmU6ICR7ZW52Lk1JTFZVU19TRUNVUkU6PX0KICAgICAgICBjb25zaXN0ZW5jeV9sZXZlbDogJHtlbnYuTUlMVlVTX0NPTlNJU1RFTkNZX0xFVkVMOj19CiAgICAgICAgY2FfcGVtX3BhdGg6ICR7ZW52Lk1JTFZVU19DQV9QRU1fUEFUSDo9fQogICAgICAgIGNsaWVudF9wZW1fcGF0aDogJHtlbnYuTUlMVlVTX0NMSUVOVF9QRU1fUEFUSDo9fQogICAgICAgIGNsaWVudF9rZXlfcGF0aDogJHtlbnYuTUlMVlVTX0NMSUVOVF9LRVlfUEFUSDo9fQogICAgICAgIHBlcnNpc3RlbmNlOgogICAgICAgICAgYmFja2VuZDoga3ZfZGVmYXVsdAogICAgICAgICAgbmFtZXNwYWNlOiB2ZWN0b3JfaW86Om1pbHZ1c19yZW1vdGUKICAgIC0gcHJvdmlkZXJfaWQ6ICR7ZW52LkVOQUJMRV9QR1ZFQ1RPUjorcGd2ZWN0b3J9CiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6cGd2ZWN0b3IKICAgICAgY29uZmlnOgogICAgICAgIGhvc3Q6ICR7ZW52LlBHVkVDVE9SX0hPU1Q6PWxvY2FsaG9zdH0KICAgICAgICBwb3J0OiAke2Vudi5QR1ZFQ1RPUl9QT1JUOj01NDMyfQogICAgICAgIGRiOiAke2Vudi5QR1ZFQ1RPUl9EQjo9fQogICAgICAgIHVzZXI6ICR7ZW52LlBHVkVDVE9SX1VTRVI6PX0KICAgICAgICBwYXNzd29yZDogJHtlbnYuUEdWRUNUT1JfUEFTU1dPUkQ6PX0KICAgICAgICBwZXJzaXN0ZW5jZToKICAgICAgICAgIGJhY2tlbmQ6IGt2X2RlZmF1bHQKICAgICAgICAgIG5hbWVzcGFjZTogdmVjdG9yX2lvOjpwZ3ZlY3RvcgogICAgLSBwcm92aWRlcl9pZDogJHtlbnYuRU5BQkxFX1FEUkFOVDorcWRyYW50LXJlbW90ZX0KICAgICAgcHJvdmlkZXJfdHlwZTogcmVtb3RlOjpxZHJhbnQKICAgICAgY29uZmlnOgogICAgICAgIGxvY2F0aW9uOiAke2Vudi5RRFJBTlRfTE9DQVRJT046PX0KICAgICAgICB1cmw6ICR7ZW52LlFEUkFOVF9VUkw6PX0KICAgICAgICBwb3J0OiAke2Vudi5RRFJBTlRfUE9SVDo9NjMzM30KICAgICAgICBncnBjX3BvcnQ6ICR7ZW52LlFEUkFOVF9HUlBDX1BPUlQ6PTYzMzR9CiAgICAgICAgcHJlZmVyX2dycGM6ICR7ZW52LlFEUkFOVF9QUkVGRVJfR1JQQzo9ZmFsc2V9CiAgICAgICAgaHR0cHM6ICR7ZW52LlFEUkFOVF9IVFRQUzo9fQogICAgICAgIGFwaV9rZXk6ICR7ZW52LlFEUkFOVF9BUElfS0VZOj19CiAgICAgICAgcHJlZml4OiAke2Vudi5RRFJBTlRfUFJFRklYOj19CiAgICAgICAgdGltZW91dDogJHtlbnYuUURSQU5UX1RJTUVPVVQ6PX0KICAgICAgICBob3N0OiAke2Vudi5RRFJBTlRfSE9TVDo9fQogICAgICAgIHBlcnNpc3RlbmNlOgogICAgICAgICAgYmFja2VuZDoga3ZfZGVmYXVsdAogICAgICAgICAgbmFtZXNwYWNlOiB2ZWN0b3JfaW86OnFkcmFudF9yZW1vdGUKICByZXNwb25zZXM6CiAgICAtIHByb3ZpZGVyX2lkOiBtZXRhLXJlZmVyZW5jZQogICAgICBwcm92aWRlcl90eXBlOiBpbmxpbmU6OmJ1aWx0aW4KICAgICAgY29uZmlnOgogICAgICAgIHBlcnNpc3RlbmNlOgogICAgICAgICAgYWdlbnRfc3RhdGU6CiAgICAgICAgICAgIGJhY2tlbmQ6IGt2X2RlZmF1bHQKICAgICAgICAgICAgbmFtZXNwYWNlOiBhZ2VudHM6Om1ldGFfcmVmZXJlbmNlCiAgICAgICAgICByZXNwb25zZXM6CiAgICAgICAgICAgIGJhY2tlbmQ6IHNxbF9kZWZhdWx0CiAgICAgICAgICAgIHRhYmxlX25hbWU6IGFnZW50c19yZXNwb25zZXMKICAgICAgICAgICAgbWF4X3dyaXRlX3F1ZXVlX3NpemU6IDEwMDAwCiAgICAgICAgICAgIG51bV93cml0ZXJzOiA0CiAgbWVzc2FnZXM6CiAgIyBJbXBsZW1lbnRzIHRoZSBBbnRocm9waWMgTWVzc2FnZXMgQVBJICgvdjEvbWVzc2FnZXMpLiBOYXRpdmUgcGFzc3Rocm91Z2ggZm9yCiAgIyBwcm92aWRlcnMgdGhhdCBzdXBwb3J0IGl0IChlLmcuIHZMTE0pOyB0cmFuc2xhdGVzIEFudGhyb3BpYyA8LT4gT3BlbkFJIENoYXQKICAjIENvbXBsZXRpb25zIGZvciBhbGwgb3RoZXIgcHJvdmlkZXJzLiBEZXBlbmRzIG9uIHRoZSBpbmZlcmVuY2UgQVBJLgogICAgLSBwcm92aWRlcl9pZDogYnVpbHRpbgogICAgICBwcm92aWRlcl90eXBlOiBpbmxpbmU6OmJ1aWx0aW4KICAgICAgY29uZmlnOgogICAgICAgIGt2c3RvcmU6CiAgICAgICAgICBiYWNrZW5kOiBrdl9kZWZhdWx0CiAgICAgICAgICBuYW1lc3BhY2U6IG1lc3NhZ2VfYmF0Y2hlcwogIHRvb2xfcnVudGltZToKICAjIE5PVEU6IGlubGluZTo6ZmlsZS1zZWFyY2ggcmVxdWlyZXMgYSAnZmlsZXMnIHByb3ZpZGVyIGF0IHJ1bnRpbWUKICAjIChjdXJyZW50bHkgaW5saW5lOjpsb2NhbGZzKS4gRG8gbm90IGFkZCBpbmxpbmU6OmxvY2FsZnMgdG8KICAjIFNUUklQUEVEX1BST1ZJREVSX1RZUEVTIGluIGJ1aWxkLnB5IHdpdGhvdXQgYWxzbyByZW1vdmluZwogICMgaW5saW5lOjpmaWxlLXNlYXJjaCBoZXJlLgogICAgLSBwcm92aWRlcl9pZDogYnJhdmUtc2VhcmNoCiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6YnJhdmUtc2VhcmNoCiAgICAgIGNvbmZpZzoKICAgICAgICBhcGlfa2V5OiAke2Vudi5CUkFWRV9TRUFSQ0hfQVBJX0tFWTo9fQogICAgICAgIG1heF9yZXN1bHRzOiAzCiAgICAtIHByb3ZpZGVyX2lkOiB0YXZpbHktc2VhcmNoCiAgICAgIHByb3ZpZGVyX3R5cGU6IHJlbW90ZTo6dGF2aWx5LXNlYXJjaAogICAgICBjb25maWc6CiAgICAgICAgYXBpX2tleTogJHtlbnYuVEFWSUxZX1NFQVJDSF9BUElfS0VZOj19CiAgICAgICAgbWF4X3Jlc3VsdHM6IDMKICAgIC0gcHJvdmlkZXJfaWQ6IGZpbGUtc2VhcmNoCiAgICAgIHByb3ZpZGVyX3R5cGU6IGlubGluZTo6ZmlsZS1zZWFyY2gKICAgICAgY29uZmlnOiB7fQogICAgLSBwcm92aWRlcl9pZDogbW9kZWwtY29udGV4dC1wcm90b2NvbAogICAgICBwcm92aWRlcl90eXBlOiByZW1vdGU6Om1vZGVsLWNvbnRleHQtcHJvdG9jb2wKICAgICAgY29uZmlnOiB7fQogIGZpbGVzOgogICMgUmVxdWlyZWQgYXQgcnVudGltZSBieSBpbmxpbmU6OmZpbGUtc2VhcmNoIChzZWUgdG9vbF9ydW50aW1lIGFib3ZlKS4KICAgIC0gcHJvdmlkZXJfaWQ6IG1ldGEtcmVmZXJlbmNlLWZpbGVzCiAgICAgIHByb3ZpZGVyX3R5cGU6IGlubGluZTo6bG9jYWxmcwogICAgICBjb25maWc6CiAgICAgICAgc3RvcmFnZV9kaXI6IC9vcHQvYXBwLXJvb3Qvc3JjLy5vZ3gvZGlzdHJpYnV0aW9ucy9yaC9maWxlcwogICAgICAgIG1ldGFkYXRhX3N0b3JlOgogICAgICAgICAgYmFja2VuZDogc3FsX2RlZmF1bHQKICAgICAgICAgIHRhYmxlX25hbWU6IGZpbGVzX21ldGFkYXRhCiAgICAtIHByb3ZpZGVyX2lkOiAke2Vudi5FTkFCTEVfUzM6K3MzfQogICAgICBwcm92aWRlcl90eXBlOiByZW1vdGU6OnMzCiAgICAgIGNvbmZpZzoKICAgICAgICBidWNrZXRfbmFtZTogJHtlbnYuUzNfQlVDS0VUX05BTUU6PX0KICAgICAgICByZWdpb246ICR7ZW52LkFXU19ERUZBVUxUX1JFR0lPTjo9dXMtZWFzdC0xfQogICAgICAgIGF3c19hY2Nlc3Nfa2V5X2lkOiAke2Vudi5BV1NfQUNDRVNTX0tFWV9JRDo9fQogICAgICAgIGF3c19zZWNyZXRfYWNjZXNzX2tleTogJHtlbnYuQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZOj19CiAgICAgICAgZW5kcG9pbnRfdXJsOiAke2Vudi5TM19FTkRQT0lOVF9VUkw6PX0KICAgICAgICBhdXRvX2NyZWF0ZV9idWNrZXQ6ICR7ZW52LlMzX0FVVE9fQ1JFQVRFX0JVQ0tFVDo9ZmFsc2V9CiAgICAgICAgbWV0YWRhdGFfc3RvcmU6CiAgICAgICAgICBiYWNrZW5kOiBzcWxfZGVmYXVsdAogICAgICAgICAgdGFibGVfbmFtZTogZmlsZXNfbWV0YWRhdGEKICBmaWxlX3Byb2Nlc3NvcnM6CiAgICAtIHByb3ZpZGVyX2lkOiBhdXRvCiAgICAgIHByb3ZpZGVyX3R5cGU6IGlubGluZTo6YXV0bwogICAgICBjb25maWc6IHt9CiAgYmF0Y2hlczoKICAgIC0gcHJvdmlkZXJfaWQ6IHJlZmVyZW5jZQogICAgICBwcm92aWRlcl90eXBlOiBpbmxpbmU6OnJlZmVyZW5jZQogICAgICBjb25maWc6CiAgICAgICAgc3Fsc3RvcmU6CiAgICAgICAgICB0YWJsZV9uYW1lOiBiYXRjaGVzCiAgICAgICAgICBiYWNrZW5kOiBzcWxfZGVmYXVsdApzdG9yYWdlOgogIGJhY2tlbmRzOgogICAga3ZfZGVmYXVsdDoKICAgICAgdHlwZToga3ZfcG9zdGdyZXMKICAgICAgaG9zdDogJHtlbnYuUE9TVEdSRVNfSE9TVDo9bG9jYWxob3N0fQogICAgICBwb3J0OiAke2Vudi5QT1NUR1JFU19QT1JUOj01NDMyfQogICAgICBkYjogJHtlbnYuUE9TVEdSRVNfREI6PW9neH0KICAgICAgdXNlcjogJHtlbnYuUE9TVEdSRVNfVVNFUjo9b2d4fQogICAgICBwYXNzd29yZDogJHtlbnYuUE9TVEdSRVNfUEFTU1dPUkQ6PW9neH0KICAgICAgdGFibGVfbmFtZTogJHtlbnYuUE9TVEdSRVNfVEFCTEVfTkFNRTo9b2d4X2t2c3RvcmV9CiAgICBzcWxfZGVmYXVsdDoKICAgICAgdHlwZTogc3FsX3Bvc3RncmVzCiAgICAgIGhvc3Q6ICR7ZW52LlBPU1RHUkVTX0hPU1Q6PWxvY2FsaG9zdH0KICAgICAgcG9ydDogJHtlbnYuUE9TVEdSRVNfUE9SVDo9NTQzMn0KICAgICAgZGI6ICR7ZW52LlBPU1RHUkVTX0RCOj1vZ3h9CiAgICAgIHVzZXI6ICR7ZW52LlBPU1RHUkVTX1VTRVI6PW9neH0KICAgICAgcGFzc3dvcmQ6ICR7ZW52LlBPU1RHUkVTX1BBU1NXT1JEOj1vZ3h9CiAgc3RvcmVzOgogICAgbWV0YWRhdGE6CiAgICAgIGJhY2tlbmQ6IGt2X2RlZmF1bHQKICAgICAgbmFtZXNwYWNlOiByZWdpc3RyeQogICAgaW5mZXJlbmNlOgogICAgICB0YWJsZV9uYW1lOiBpbmZlcmVuY2Vfc3RvcmUKICAgICAgYmFja2VuZDogc3FsX2RlZmF1bHQKICAgICAgbWF4X3dyaXRlX3F1ZXVlX3NpemU6IDEwMDAwCiAgICAgIG51bV93cml0ZXJzOiA0CiAgICBjb252ZXJzYXRpb25zOgogICAgICB0YWJsZV9uYW1lOiBvcGVuYWlfY29udmVyc2F0aW9ucwogICAgICBiYWNrZW5kOiBzcWxfZGVmYXVsdAogICAgcHJvbXB0czoKICAgICAgbmFtZXNwYWNlOiBwcm9tcHRzCiAgICAgIGJhY2tlbmQ6IGt2X2RlZmF1bHQKICAgIGNvbm5lY3RvcnM6CiAgICAgIHRhYmxlX25hbWU6IGNvbm5lY3RvcnMKICAgICAgYmFja2VuZDogc3FsX2RlZmF1bHQKICAgIHZlY3Rvcl9zdG9yZXM6CiAgICAgIGJhY2tlbmQ6IHNxbF9kZWZhdWx0CiAgICAgIHRhYmxlX25hbWU6IHZlY3Rvcl9zdG9yZV9tZXRhZGF0YQpyZWdpc3RlcmVkX3Jlc291cmNlczoKICBtb2RlbHM6CiAgICAtIG1ldGFkYXRhOgogICAgICAgIGVtYmVkZGluZ19kaW1lbnNpb246ICR7ZW52LkVNQkVERElOR19ESU1FTlNJT046PTc2OH0KICAgICAgbW9kZWxfaWQ6ICR7ZW52LkVNQkVERElOR19NT0RFTDo9fQogICAgICBwcm92aWRlcl9pZDogJHtlbnYuRU1CRURESU5HX1BST1ZJREVSOj12bGxtLWVtYmVkZGluZ30KICAgICAgcHJvdmlkZXJfbW9kZWxfaWQ6ICR7ZW52LkVNQkVERElOR19QUk9WSURFUl9NT0RFTF9JRDo9aWJtLWdyYW5pdGUvZ3Jhbml0ZS1lbWJlZGRpbmctMTI1bS1lbmdsaXNofQogICAgICBtb2RlbF90eXBlOiBlbWJlZGRpbmcKICB2ZWN0b3JfZGJzOiBbXQogIHRvb2xfZ3JvdXBzOgogICAgLSB0b29sZ3JvdXBfaWQ6IGJ1aWx0aW46OndlYnNlYXJjaAogICAgICBwcm92aWRlcl9pZDogdGF2aWx5LXNlYXJjaAogICAgLSB0b29sZ3JvdXBfaWQ6IGJ1aWx0aW46OnJhZwogICAgICBwcm92aWRlcl9pZDogZmlsZS1zZWFyY2gKdmVjdG9yX3N0b3JlczoKICBhbm5vdGF0aW9uX3Byb21wdF9wYXJhbXM6CiAgICBlbmFibGVfYW5ub3RhdGlvbnM6IHRydWUKICAgIGFubm90YXRpb25faW5zdHJ1Y3Rpb25fdGVtcGxhdGU6ICJDaXRlIHNvdXJjZXMgaW1tZWRpYXRlbHkgYXQgdGhlIGVuZCBvZiBzZW50ZW5jZXMgdXNpbmcgPHxmaWxlLWlkfD4gZm9ybWF0LiIKdGVsZW1ldHJ5OgogIGVuYWJsZWQ6IHRydWUKc2VydmVyOgogIHBvcnQ6IDgzMjEKICByZWdpc3RyeV9yZWZyZXNoX2ludGVydmFsX3NlY29uZHM6ICR7ZW52LlJFR0lTVFJZX1JFRlJFU0hfSU5URVJWQUxfU0VDT05EUzo9MzAwfQogIGF1dGg6CiAgICBwcm92aWRlcl9jb25maWc6CiAgICAgIHR5cGU6ICR7ZW52LkFVVEhfSVNTVUVSOitvYXV0aDJfdG9rZW59CiAgICAgIGF1ZGllbmNlOiAke2Vudi5BVVRIX0FVRElFTkNFOj1vZ3h9CiAgICAgIGlzc3VlcjogJHtlbnYuQVVUSF9JU1NVRVI6PX0KICAgICAgandrczoKICAgICAgICB1cmk6ICR7ZW52LkFVVEhfSldLU19VUkk6PX0KICAgICAgICBrZXlfcmVjaGVja19wZXJpb2Q6ICR7ZW52LkFVVEhfSldLU19SRUNIRUNLX1BFUklPRDo9MzYwMH0KICAgICAgdmVyaWZ5X3RsczogJHtlbnYuQVVUSF9WRVJJRllfVExTOj10cnVlfQogICAgYWNjZXNzX3BvbGljeToKICAgICAgLSBwZXJtaXQ6CiAgICAgICAgICBhY3Rpb25zOiBbcmVhZF0KICAgICAgICB3aGVuOiByZXNvdXJjZSBpcyB1bm93bmVkCiAgICAgICAgZGVzY3JpcHRpb246ICJBbGwgdXNlcnMgY2FuIHJlYWQgc3lzdGVtIHJlc291cmNlcyIKICAgICAgLSBwZXJtaXQ6CiAgICAgICAgICBhY3Rpb25zOiBbY3JlYXRlXQogICAgICAgIGRlc2NyaXB0aW9uOiAiQXV0aGVudGljYXRlZCB1c2VycyBjYW4gY3JlYXRlIHJlc291cmNlcyIKICAgICAgLSBwZXJtaXQ6CiAgICAgICAgICBhY3Rpb25zOiBbcmVhZCwgdXBkYXRlLCBkZWxldGVdCiAgICAgICAgd2hlbjogdXNlciBpcyBvd25lcgogICAgICAgIGRlc2NyaXB0aW9uOiAiT3duZXJzIGNhbiBtYW5hZ2UgdGhlaXIgb3duIHJlc291cmNlcyIK" \
Expand Down
19 changes: 16 additions & 3 deletions Containerfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,24 @@ ENV UV_INDEX_STRATEGY=unsafe-best-match

COPY distribution/constraints.txt ${APP_ROOT}/constraints.txt
COPY distribution/requirements.txt ${APP_ROOT}/requirements.txt
RUN uv pip install --constraint ${APP_ROOT}/constraints.txt -r ${APP_ROOT}/requirements.txt

COPY --chmod=755 distribution/install-common.sh ${APP_ROOT}/install-common.sh
# Package docling transitively pulls in opencv-python via rapidocr.
# opencv-python requires libGL.so.1 (absent in UBI). Swap it for the headless
# variant after install, pinned to the exact version the resolver chose.
RUN uv pip install --constraint ${APP_ROOT}/constraints.txt -r ${APP_ROOT}/requirements.txt \
&& OPENCV_VERSION=$(uv pip show opencv-python 2>/dev/null | awk '/^Version:/{print $2}') \
&& [ -n "${OPENCV_VERSION}" ] || { echo "ERROR: opencv-python not found after install"; exit 1; } \
&& uv pip uninstall opencv-python \
&& uv pip install --constraint ${APP_ROOT}/constraints.txt "opencv-python-headless==${OPENCV_VERSION}"

COPY distribution/fetch_artifacts.py ${APP_ROOT}/fetch_artifacts.py
COPY --chmod=755 distribution/copy-artifacts.sh ${APP_ROOT}/copy-artifacts.sh
COPY distribution/artifacts.lock.yaml ${APP_ROOT}/artifacts.lock.yaml
RUN --mount=type=cache,target=/var/cache/artifacts,uid=1001,gid=0 \
uv run ${APP_ROOT}/fetch_artifacts.py ${APP_ROOT}/artifacts.lock.yaml /var/cache/artifacts \
&& ${APP_ROOT}/copy-artifacts.sh /var/cache/artifacts
ENV DOCLING_ARTIFACTS_PATH="${APP_ROOT}/.cache/docling/models"
RUN ${APP_ROOT}/install-common.sh
ENV HF_HOME="${APP_ROOT}/.cache/huggingface"
ENV TIKTOKEN_CACHE_DIR="${APP_ROOT}/.cache/tiktoken"

{config_labels}
Expand Down
Loading
Loading