# syntax=docker/dockerfile:1 # GR00T Docker image (x86_64 + aarch64) # # Single Dockerfile for both architectures. flash-attn is installed from # official cu12torch2.9 cp312 release wheels (x86_64 + aarch64); on aarch64 # (GB200, Grace Hopper) torchcodec is installed from the prebuilt wheel under # scripts/deployment/dgpu/wheels/ via a pyproject.toml path source. If that # wheel is missing, the Docker build bootstraps it from source first. # # Build: # docker build -f docker/Dockerfile -t gr00t . # # Run: # docker run -it --rm --gpus all --ipc=host gr00t FROM nvidia/cuda:12.8.0-devel-ubuntu24.04 SHELL ["/bin/bash", "-c"] ENV DEBIAN_FRONTEND=noninteractive \ NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute \ GR00T_GLOBAL_VENV=/opt/gr00t-venv \ UV_PROJECT_ENVIRONMENT=/opt/gr00t-venv \ PYTHON=/usr/bin/python \ CUDA_HOME=/usr/local/cuda \ PATH=/usr/local/cuda/bin:${PATH} \ LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH} # System dependencies RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked < deadsnakes. add_python310_retry() { for attempt in 1 2 3 4 5; do if add-apt-repository -y ppa:deadsnakes/ppa \ && apt_update \ && apt-get "${APT_RETRY_OPTS[@]}" install -y --no-install-recommends \ python3.10 \ python3.10-venv \ python3.10-dev; then return 0 fi if [ "$attempt" != "5" ]; then rm -rf /var/lib/apt/lists/* apt_update || true sleep $((attempt * 10)) fi done return 1 } add_python310_retry pip_install_retry() { for attempt in 1 2 3 4 5; do # Ubuntu 24.04's system Python is PEP 668 "externally managed"; this only # bootstraps pip/setuptools/wheel before uv builds its own venv, so opting # out is safe inside the image. --ignore-installed avoids trying to # uninstall debian's pip 24.0 (no RECORD file -> "Cannot uninstall"). if python -m pip install --upgrade --retries 5 --break-system-packages --ignore-installed pip setuptools wheel; then return 0 fi sleep $((attempt * 10)) done return 1 } pip_install_retry curl --retry 5 --retry-delay 10 --retry-max-time 300 -LsSf https://astral.sh/uv/0.8.14/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh INNEREOF WORKDIR /tmp/gr00t-venv-build # Install Python dependencies from lockfile # The wheels/ dir must be present before `uv sync` because pyproject.toml # references the aarch64 torchcodec wheel there as a path source. COPY pyproject.toml uv.lock ./ COPY scripts/deployment/dgpu/bootstrap_wheels.sh ./scripts/deployment/dgpu/bootstrap_wheels.sh COPY scripts/deployment/dgpu/wheels/ ./scripts/deployment/dgpu/wheels/ RUN < "${GR00T_GLOBAL_VENV}/.gr00t-uv-lock.sha256" mkdir -p /opt/gr00t-image-metadata cp pyproject.toml uv.lock /opt/gr00t-image-metadata/ cd / rm -rf /tmp/gr00t-venv-build INNEREOF WORKDIR / RUN mkdir -p /workspace && ln -sfn "${GR00T_GLOBAL_VENV}" /workspace/.venv WORKDIR /workspace ENV PATH="${GR00T_GLOBAL_VENV}/bin:${PATH}" \ VIRTUAL_ENV="${GR00T_GLOBAL_VENV}" # EGL/Vulkan setup for headless rendering (MuJoCo, PyOpenGL) RUN mkdir -p /usr/share/glvnd/egl_vendor.d && \ cat >/usr/share/glvnd/egl_vendor.d/10_nvidia.json <<'JSONEOF' { "file_format_version" : "1.0.0", "ICD" : { "library_path" : "libEGL_nvidia.so.0" } } JSONEOF RUN mkdir -p /usr/share/vulkan/icd.d && \ cat >/usr/share/vulkan/icd.d/nvidia_icd.json <<'JSONEOF' { "file_format_version": "1.0.0", "ICD": { "library_path": "libGLX_nvidia.so.0", "api_version": "1.2.140" } } JSONEOF ENV MUJOCO_GL="egl" \ PYOPENGL_PLATFORM="egl" \ __EGL_VENDOR_LIBRARY_FILENAMES="/usr/share/glvnd/egl_vendor.d/10_nvidia.json" # aarch64 torchcodec is installed from the repo-local wheel by `uv sync` above # via a pyproject.toml path source; the wheel is built from source by # bootstrap_wheels.sh before sync (then committed back) if missing. flash-attn # comes from official release URLs — no source build needed. CMD ["/bin/bash"]