File size: 5,792 Bytes
9a069e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
FROM --platform=linux/amd64 pytorch/pytorch:2.11.0-cuda12.8-cudnn9-runtime AS segment-algorithm-amd64

# torch 2.11.0 + torchvision are pre-installed in the base image (CUDA 12.8).
# requirements.txt only lists additional dependencies.
#
# This base image is the recommended default, not a hard requirement. It is chosen
# because it is the ONE PyTorch build that runs on both evaluation GPUs unmodified:
# an NVIDIA RTX PRO 6000 Blackwell (compute capability sm_120) and an NVIDIA L40S
# (sm_89). Its CUDA 12.8 kernels cover sm_75/80/86/90/100/120 β€” Blackwell natively
# and the L40S via its sm_86 kernels (a CUDA binary runs on any later minor
# revision of the same major capability). So one image serves whichever GPU you
# select on the platform, with no rebuild.
#
# If you change it, know the two limits it steers around: CUDA 12.4/12.6 wheels
# stop at sm_90 and abort on Blackwell ("not compatible with the current PyTorch
# installation"); CUDA 13.0 wheels cover both GPUs but need a host driver >= 580 β€”
# the RTX PRO 6000 fleet has it (595), the L40S fleet does not. If your submission
# targets ONLY the RTX PRO 6000 (offered on the SEGMENT and PROCEDURE tracks), a
# newer CUDA/torch is a valid choice β€” see the guard below for the one line to relax.

ENV PYTHONUNBUFFERED=1

# ── System packages ───────────────────────────────────────────────────────────
# The slim -runtime base image ships neither the shared libraries that
# opencv-python (a dependency of orena-focus) needs at import time, nor any
# compiler toolchain. Install system packages HERE, while the build still runs
# as root β€” everything below runs as the unprivileged 'user'. If one of your
# pip dependencies compiles from source (e.g. flash-attn), add build-essential.
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libgl1 \
        libglib2.0-0 \
        libxcb1 \
    && rm -rf /var/lib/apt/lists/*

RUN groupadd -r user && useradd -m --no-log-init -r -g user user
USER user

WORKDIR /opt/app

COPY --chown=user:user requirements.txt /opt/app/

# If one of your dependencies compiles CUDA extensions during the build (e.g.
# flash-attn from source), uncomment this so it emits kernels for both evaluation
# GPUs rather than only for the card in your build machine:
# ENV TORCH_CUDA_ARCH_LIST="8.0;8.6;8.9;9.0;12.0+PTX"

# --break-system-packages: this base image's Python is Ubuntu's system Python,
# which is marked externally-managed (PEP 668), so pip refuses to install without
# it. Nothing is actually broken β€” `--user` still installs into the unprivileged
# user's own ~/.local, leaving the system packages untouched.
RUN python -m pip install \
    --user \
    --break-system-packages \
    --no-cache-dir \
    --no-color \
    --requirement /opt/app/requirements.txt

# ── Guard: is torch still the recommended CUDA 12.8 build? ────────────────────
# This enforces the recommendation above so an ACCIDENTAL swap cannot reach the
# platform unnoticed. If one of your dependencies needs a torch version this image
# does not have, pip quietly replaces the CUDA 12.8 build with the default PyPI
# wheel (built against CUDA 13.0). That wheel needs a host driver >= 580.65.06; the
# L40S fleet runs 570.211.01, so it cannot start there. Failing the build now beats
# failing every job after you submit.
#
# Both halves matter. The CUDA version is what the driver floor depends on, and it
# is NOT visible in the architecture list: the CUDA 13.0 wheel advertises the very
# same sm_ list as the 12.8 one. The arch list is still checked because it is what
# an older CUDA 12.4/12.6 wheel gets wrong. get_arch_list() returns [] with no GPU
# visible β€” a docker build never has one β€” so the flags compiled into the wheel are
# read directly.
#
# Targeting the RTX PRO 6000 only, and want a newer CUDA? Then this default no
# longer applies to you: drop the `cuda.startswith('12.8')` assert below (keep the
# sm_120 arch assert, so a build with no Blackwell kernels is still caught).
RUN python -c "import torch; \
flags = torch._C._cuda_getArchFlags() or ''; \
cuda = torch.version.cuda or ''; \
print('torch', torch.__version__, '| cuda', cuda, '|', flags); \
assert cuda.startswith('12.8'), 'torch was replaced by a CUDA ' + cuda + ' build; the L40S driver cannot run it'; \
assert 'sm_120' in flags and 'sm_86' in flags, 'torch build misses a required GPU architecture: ' + repr(flags)"

# ── Model definition + weights ────────────────────────────────────────────────
# resources/ holds the model definition (model.py) and a small committed dummy
# checkpoint (dummy_weights.pt). For a real submission, replace dummy_weights.pt
# with your trained checkpoint.
#
# ECR layer-size limit: a single image layer must not exceed 50 GB, and each
# COPY instruction produces exactly one layer. A checkpoint large enough to push
# one COPY past that limit must be split into chunks and copied with several COPY
# instructions (one layer each), then reassembled at runtime β€” e.g. pre-split
# with `split -b 45G weights.pt resources/weights.part-` and:
#     COPY --chown=user:user resources/weights.part-aa /opt/app/resources/
#     COPY --chown=user:user resources/weights.part-ab /opt/app/resources/
#     COPY --chown=user:user resources/weights.part-ac /opt/app/resources/
# reassembling with `cat resources/weights.part-* > weights.pt` before load.
COPY --chown=user:user resources/ /opt/app/resources/

COPY --chown=user:user inference.py /opt/app/

ENTRYPOINT ["python", "inference.py"]