aeye-backend / Dockerfile
wonjun12's picture
Code is private: the container fetches bundle 81962887e0d17f58 from the private repo at start-up (public files e0acfbcd2cee003d)
b48a476 verified
Raw History Blame Contribute Delete
5.35 kB
# A-EYE backend. The application code is private; the container fetches it when it starts.
FROM python:3.11-slim@sha256:e88e9763f943ec1834f992a4b51e0f24500486803e8bc534e5767af9ea65f6ce
ENV PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
RUN useradd -m -u 1000 appuser
ENV HOME=/home/appuser \
HF_HOME=/home/appuser/.cache/huggingface
WORKDIR /app
RUN pip install --upgrade pip \
&& pip install torch==2.8.0 torchvision==0.23.0 --index-url https://download.pytorch.org/whl/cpu \
&& pip install 'annotated-doc==0.0.5' 'annotated-types==0.8.0' 'anyio==4.15.1' 'certifi==2026.7.22' 'charset-normalizer==3.5.2' 'click==8.5.0' 'fastapi==0.141.1' 'filelock==3.32.3' 'fsspec==2026.7.0' 'h11==0.16.0' 'hf-xet==1.7.0' 'httptools==0.8.0' 'huggingface_hub==0.36.2' 'idna==3.20' 'Jinja2==3.1.6' 'MarkupSafe==3.0.3' 'mpmath==1.3.0' 'networkx==3.6.1' 'numpy==2.4.6' 'packaging==26.3' 'pillow==12.3.0' 'pydantic==2.14.0' 'pydantic_core==2.50.0' 'python-dotenv==1.2.4' 'python-multipart==0.0.32' 'PyYAML==6.0.3' 'regex==2026.9.29' 'requests==2.34.2' 'safetensors==0.8.0' 'scipy==1.17.1' 'starlette==1.7.0' 'sympy==1.14.0' 'tokenizers==0.22.2' 'tqdm==4.70.1' 'transformers==4.57.6' 'typing-inspection==0.4.4' 'typing_extensions==4.16.0' 'urllib3==2.8.0' 'uvicorn==0.34.0' 'uvloop==0.23.0' 'watchfiles==1.3.0' 'websockets==17.2'
RUN python -c "from transformers import CLIPVisionModelWithProjection as M; M.from_pretrained('openai/clip-vit-large-patch14', revision='32bd64288804d66eefd0ccbe215aa642df71cc41')" \
&& python -c "from transformers import AutoModel; AutoModel.from_pretrained('facebook/dinov2-small', revision='ed25f3a31f01632728cabb09d1542f84ab7b0056')" \
&& chown -R appuser:appuser /home/appuser/.cache
RUN chown appuser:appuser /app
ENV AEYE_CODE_REPO=wonjun12/aeye-weights \
AEYE_CODE_REVISION=515b3df3b6fb7913b2ba7d790daae3e923c654b2 \
AEYE_CODE_FILE=code/aeye-backend-81962887e0d17f58.tar.gz \
AEYE_CODE_SHA256=81962887e0d17f5843bc5baa582a50b828a35ccc1172387995d61843bb1e1a23
USER appuser
ENV AEYE_DEVICE=cpu \
AEYE_TORCH_THREADS=2 \
AEYE_MAX_CONCURRENCY=1 \
AEYE_KEY_PER_MINUTE=10 \
AEYE_KEY_PER_DAY=1000 \
AEYE_HEATMAP_STYLE=spotlight \
AEYE_INPUT_KIND=on \
TRANSFORMERS_OFFLINE=1
ENV AEYE_WEIGHTS_REPO=wonjun12/aeye-weights \
AEYE_WEIGHTS_REVISION=f042633672aa30361234674c43d6c35373e0d71a \
AEYE_WEIGHTS_SHA256_BEST49=145c18f4cd7fc430d223cdec7f6abac1e29124155f8628648a5ef86173975134 \
AEYE_WEIGHTS_SHA256_BEST63=b93733e88c69b76581d49150d097dafd686e21f9d355d4665dcb0ffbee30742d \
AEYE_WEIGHTS_SHA256_BEST69=0f423cc566a7dfc8aa991f81ddf4e6410291106309841fdc09265c387aebf0df \
AEYE_WEIGHTS_SHA256_BEST69_LOC=6562f22ecd262aecdad5aaf54a8554cd239f2e1d40b6671adbdb2d9ecdc0ee82 \
AEYE_WEIGHTS_SHA256_BEST91=d3dc13a6f68947c187af515a5b75aa2609696b44f3c829b9e5297836db7e8ffe \
AEYE_WEIGHTS_SHA256_BEST91_LOC=fe5997eb90c22a75e3a31a66decfdf73c0775fe6650ad1d178ccbafa3bd0f1d9
ENV VERDICT_MODEL_PATH=/app/models/best91.pt \
HEATMAP_MODEL_PATH=/app/models/best91_loc.pt \
AEYE_BAND_T5=0.854339 \
AEYE_BAND_T1=0.981525 \
AEYE_BANDS_FOR=246d25f0c991bb95 \
AEYE_FUSION=on \
AEYE_FUSION_PATH=./fusion/fusion_rc2.json
ENV AEYE_SCREEN_PATH=on \
AEYE_SCREEN_PATH_RULE=./screen_rules/screen_head_v3.json \
AEYE_SCREEN_PATH_RULE_ID=39f10adf3dbdae13 \
AEYE_SCREEN_PATH_FOR=246d25f0c991bb95
EXPOSE 7860
CMD ["python", "-c", "import compileall, hashlib, io, os, sys, tarfile, time, requests\nARGV = ['python', '-m', 'uvicorn', 'main_hybrid:app', '--host', '0.0.0.0', '--port', '7860', '--workers', '1', '--limit-concurrency', '64', '--timeout-keep-alive', '5', '--no-access-log']\nrepo, rev, path, want = (os.environ[k] for k in ('AEYE_CODE_REPO', 'AEYE_CODE_REVISION', 'AEYE_CODE_FILE', 'AEYE_CODE_SHA256'))\nurl = 'https://huggingface.co/%s/resolve/%s/%s' % (repo, rev, path)\ntoken = os.environ.get('HF_TOKEN', '').strip()\ndelay, deadline = 5, time.time() + 600\nwhile True:\n try:\n r = requests.get(url, headers={'Authorization': 'Bearer ' + token}, timeout=(10, 300))\n why = 'HTTP %d' % r.status_code\n except requests.RequestException as exc:\n r, why = None, type(exc).__name__\n if r is not None and r.status_code == 200:\n break\n if r is not None and r.status_code in (401, 403, 404):\n sys.exit('[start] the code bundle is not readable (%s) - is the Space secret HF_TOKEN set?' % why)\n if time.time() > deadline:\n sys.exit('[start] the code bundle could not be downloaded for 10 minutes (%s)' % why)\n print('[start] code download: %s - retrying in %ds' % (why, delay), flush=True)\n time.sleep(delay)\n delay = min(delay * 2, 60)\ndata = r.content\ngot = hashlib.sha256(data).hexdigest()\nif got != want:\n sys.exit('[start] code bundle sha256 %s is not the pinned %s' % (got, want))\ntarfile.open(fileobj=io.BytesIO(data), mode='r:gz').extractall('/app', filter='data')\nif not compileall.compile_dir('/app', legacy=True, quiet=1):\n sys.exit('[start] the code bundle did not compile')\nfor folder, _, names in os.walk('/app'):\n for name in names:\n if name.endswith('.py'):\n os.remove(os.path.join(folder, name))\nprint('[start] code %s (%s) ready' % (path, got[:16]), flush=True)\nos.chdir('/app')\nos.execvp(ARGV[0], ARGV)"]