annotation-studio / Dockerfile
pepijn223's picture
pepijn223 HF Staff
Consolidate native hand and Flora Jobs in Annotation Studio; use the official dataset viewer
b00f3e3 verified
Raw History Blame Contribute Delete
9.25 kB
FROM oven/bun:1.3.10 AS frontend
WORKDIR /build
COPY frontend/package.json frontend/bun.lock ./
RUN bun install --frozen-lockfile
COPY frontend/ ./
RUN bun run build
# Build Flora's dependencies on CPU without credentials or Flora model weights.
# Verified upstream PyTorch image digest, CUDA 12.8 / Torch 2.11.0.
FROM pytorch/pytorch:2.11.0-cuda12.8-cudnn9-devel@sha256:53ab3de62f6101d1e42f9be28623ab7a468a24c070d632f211ed576e30b6abd3 AS flora-build
ENV DEBIAN_FRONTEND=noninteractive TORCH_CUDA_ARCH_LIST=9.0 MAX_JOBS=4
RUN apt-get update && apt-get install -y --no-install-recommends python3-venv \
&& rm -rf /var/lib/apt/lists/* \
&& python -m venv --system-site-packages /opt/flora-venv
ENV PATH=/opt/flora-venv/bin:$PATH
WORKDIR /workspace/app
COPY worker-requirements.txt flora-requirements.txt flora-acceleration-requirements.txt ./
# Keep the reference worker/native dependency overlay order.
RUN python -m pip install --no-cache-dir -r worker-requirements.txt
RUN python -m pip install --no-cache-dir -r flora-requirements.txt
COPY build_causal_conv1d.py ./
ENV MAX_JOBS=1
RUN python build_causal_conv1d.py
RUN python -m pip install --no-cache-dir --no-build-isolation -r flora-acceleration-requirements.txt
RUN python -c "import causal_conv1d; from fla.ops.gated_delta_rule import chunk_gated_delta_rule, fused_recurrent_gated_delta_rule"
COPY *.py *.txt prompt-templates.json pipeline-source.tar.gz pipeline-version.json ./
RUN python bootstrap.py
COPY requirements.txt ./
RUN python -m venv --system-site-packages /opt/studio-venv
RUN /opt/studio-venv/bin/python -m pip install --no-cache-dir -r requirements.txt
RUN /opt/flora-venv/bin/python -c "from importlib.metadata import version; assert version('huggingface_hub') == '1.33.0'; assert version('transformers') == '5.8.1'"
# Camera operators arrive as verified wheels; this image needs no CUDA compiler.
FROM pytorch/pytorch:2.11.0-cuda12.8-cudnn9-runtime@sha256:eee11b3b3872a8c838e35ef48f08b2d5def2080902c7f666831310ca1a0ef2be AS hand-base
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends git ffmpeg libglib2.0-0 python3-venv \
&& rm -rf /var/lib/apt/lists/*
# Isolate the controller, camera and hand dependencies to retain their CUDA ABIs.
FROM hand-base AS hand-build
ENV UV_PYTHON_INSTALL_DIR=/opt/uv-python
RUN python -m pip install --break-system-packages --no-cache-dir uv==0.12.11 \
&& uv python install 3.10.20 \
&& uv venv --python 3.10.20 /opt/droid \
&& uv venv --python 3.10.20 /opt/egohand \
&& python -m venv --system-site-packages /opt/hand-controller
WORKDIR /opt/hand-worker
COPY hand-runtime/camera-requirements.txt hand-runtime/egohand-requirements.txt hand-runtime/worker-requirements.txt ./
RUN uv pip install --python /opt/droid/bin/python torch==2.8.0 torchvision==0.23.0 --index-url https://download.pytorch.org/whl/cu128
RUN uv pip install --python /opt/droid/bin/python -r /opt/hand-worker/camera-requirements.txt \
&& uv pip install --python /opt/droid/bin/python torch-scatter==2.1.2+pt28cu128 --find-links https://data.pyg.org/whl/torch-2.8.0+cu128.html \
&& uv pip install --python /opt/droid/bin/python git+https://github.com/microsoft/MoGe.git@74fbce054ebed49800de42d0ad0e83495065719a --no-deps
RUN uv pip install --python /opt/egohand/bin/python -r /opt/hand-worker/egohand-requirements.txt \
&& /opt/hand-controller/bin/python -m pip install --no-cache-dir -r /opt/hand-worker/worker-requirements.txt
RUN git clone https://github.com/NVlabs/GEM-X.git /opt/GEM-X \
&& git -C /opt/GEM-X checkout --detach 20555befe2fbbe5b2015e1fff7ff214dc18ea9d6 \
&& uv pip install --python /opt/egohand/bin/python --no-deps -e /opt/GEM-X
COPY hand-runtime/camera-adapter-source.tar.gz hand-runtime/camera-native-source.tar.gz /tmp/
RUN mkdir -p /opt/camera-adapter /opt/hand-camera \
&& tar -xzf /tmp/camera-adapter-source.tar.gz -C /opt/camera-adapter \
&& tar -xzf /tmp/camera-native-source.tar.gz -C /opt/hand-camera
COPY hand-runtime/camera-wheels /opt/hand-worker/camera-wheels
COPY hand-runtime/verify_camera_wheels.py hand-runtime/image-version.json /opt/hand-worker/
RUN python /opt/hand-worker/verify_camera_wheels.py /opt/hand-worker/camera-wheels /opt/hand-worker/image-version.json \
&& uv pip install --python /opt/droid/bin/python --no-deps /opt/hand-worker/camera-wheels/wheels/*.whl
# The frozen camera wrapper expects these source, checkpoint and plan aliases.
RUN for source in /opt/hand-camera/release-195fps-verified/DROID-W/*; do \
name=$(basename "$source"); \
if [ ! -e "/opt/hand-camera/DROID-on/$name" ]; then ln -s "$source" "/opt/hand-camera/DROID-on/$name"; fi; \
done \
&& mkdir -p /opt/hand-camera/moge-joint-vio/weights \
&& ln -s /workspace/hand-assets/camera/moge-small.pt /opt/hand-camera/moge-joint-vio/weights/small.pt \
&& ln -s /workspace/hand-assets/camera /opt/hand-camera/release-195fps-verified/DROID-W/pretrained \
&& ln -s /opt/hand-camera/release-195fps-verified/DROID-W/pretrained /opt/hand-camera/DROID-on/pretrained \
&& ln -s /workspace/hand-cache/camera-artifacts /opt/hand-camera/speed-round24/artifacts
RUN rm -rf /opt/hand-camera/release-195fps-verified/DROID-W/build \
/opt/hand-camera/release-195fps-verified/DROID-W/thirdparty/lietorch/build /tmp/*.tar.gz
FROM hand-build AS hand-models
COPY hand-runtime/model-assets/ /model-assets/
COPY hand-runtime/model-sources.json hand-runtime/build_model_assets.py hand-runtime/egohand-checkpoint-template.zip /opt/hand-worker/
RUN /opt/egohand/bin/python /opt/hand-worker/build_model_assets.py /model-assets /opt/hand-worker/model-sources.json
FROM hand-base AS hand-runtime
COPY --from=hand-build /opt/uv-python /opt/uv-python
COPY --from=hand-build /opt/droid /opt/droid
COPY --from=hand-build /opt/egohand /opt/egohand
COPY --from=hand-build /opt/hand-controller /opt/hand-controller
COPY --from=hand-build /opt/GEM-X /opt/GEM-X
COPY --from=hand-build /opt/camera-adapter /opt/camera-adapter
COPY --from=hand-build /opt/hand-camera /opt/hand-camera
COPY hand-runtime/image-version.json hand-runtime/health.py hand-runtime/verify_runtime_imports.py /opt/hand-worker/
COPY hand-runtime/camera-startup-source.tar.gz /tmp/
COPY hand-runtime/camera-startup-sources.json hand-runtime/install_startup_sources.py /opt/hand-worker/
RUN python /opt/hand-worker/install_startup_sources.py /tmp/camera-startup-source.tar.gz /opt/hand-worker/camera-startup-sources.json /opt/hand-worker/image-version.json /opt/hand-camera \
&& rm /tmp/camera-startup-source.tar.gz
ENV PATH=/opt/hand-controller/bin:$PATH PYTHONUNBUFFERED=1 HF_HUB_DISABLE_TELEMETRY=1 PYTHONDONTWRITEBYTECODE=1
ENV HOME=/home/user XDG_CACHE_HOME=/home/user/.cache
ENV PYTHONPATH=/opt/camera-adapter/src GDP_TRT_UPDATE=1
ENV DROID_SITE=/opt/droid/lib/python3.10/site-packages EGO_SITE=/opt/egohand/lib/python3.10/site-packages
ENV DROID_LIBRARY_PATH=${DROID_SITE}/tensorrt_libs:${DROID_SITE}/nvidia/cu12/lib:${DROID_SITE}/nvidia/cudnn/lib:${DROID_SITE}/nvidia/cuda_runtime/lib:${DROID_SITE}/nvidia/cublas/lib:${DROID_SITE}/nvidia/cufft/lib:${DROID_SITE}/nvidia/curand/lib:${DROID_SITE}/nvidia/cuda_nvrtc/lib
ENV EGO_LIBRARY_PATH=${EGO_SITE}/tensorrt_libs:${EGO_SITE}/nvidia/cudnn/lib:${EGO_SITE}/nvidia/cu13/lib:${DROID_SITE}/nvidia/cuda_runtime/lib:${DROID_SITE}/nvidia/cublas/lib:${DROID_SITE}/nvidia/cufft/lib:${DROID_SITE}/nvidia/curand/lib:${DROID_SITE}/nvidia/cuda_nvrtc/lib
RUN if ! getent passwd 1000 >/dev/null; then useradd -m -u 1000 user; fi \
&& mkdir -p /workspace /home/user/.cache && chown -R 1000:1000 /workspace /home/user
USER 1000
WORKDIR /workspace
COPY --from=hand-models --chown=1000:1000 /model-assets /workspace/hand-assets
COPY hand-runtime/model-sources.json hand-runtime/build_model_assets.py /opt/hand-worker/
RUN python /opt/hand-worker/build_model_assets.py /workspace/hand-assets /opt/hand-worker/model-sources.json --verify-only
RUN python /opt/hand-worker/verify_runtime_imports.py all
# One public image supplies the Studio UI, Flora Jobs and native hand Jobs.
FROM hand-runtime AS studio
COPY --from=flora-build /opt/flora-venv /opt/flora-venv
COPY --from=flora-build /opt/studio-venv /opt/studio-venv
COPY --from=flora-build --chown=1000:1000 /workspace/source /workspace/source
WORKDIR /workspace/app
ENV PATH=/opt/flora-venv/bin:$PATH
ENV PYTHONPATH=/workspace/source/src:/workspace/app PYTHONUNBUFFERED=1 HF_HUB_DISABLE_TELEMETRY=1
ENV FLORA_EXECUTION=accelerated FLORA_BATCH_SIZE=8 FLORA_ENABLE_INFERENCE=1
COPY --chown=1000:1000 *.py *.txt *.json pipeline-source.tar.gz Dockerfile README.md THIRD_PARTY.md VISUALIZER-LICENSE TRANSFORMERS-LICENSE /workspace/app/
COPY --from=frontend --chown=1000:1000 /build/dist /workspace/app/frontend/dist
RUN python -c "import worker, torch, causal_conv1d; from fla.ops.gated_delta_rule import chunk_gated_delta_rule, fused_recurrent_gated_delta_rule; assert torch.__version__.split('+')[0] == '2.11.0'"
RUN PYTHONPATH=/opt/camera-adapter/src /opt/hand-controller/bin/python /opt/hand-worker/verify_runtime_imports.py all
USER 1000
EXPOSE 7860
CMD ["/opt/studio-venv/bin/python", "-m", "uvicorn", "server:app", "--host", "0.0.0.0", "--port", "7860", "--no-access-log"]