Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
46 changes: 0 additions & 46 deletions .basedpyright/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -5628,24 +5628,6 @@
}
}
],
"./positronic/simulator/env_server/client.py": [
{
"code": "reportArgumentType",
"range": {
"startColumn": 22,
"endColumn": 33,
"lineCount": 1
}
},
{
"code": "reportArgumentType",
"range": {
"startColumn": 26,
"endColumn": 50,
"lineCount": 1
}
}
],
"./positronic/simulator/env_server/proxy.py": [
{
"code": "reportOptionalMemberAccess",
Expand All @@ -5656,24 +5638,6 @@
}
}
],
"./positronic/simulator/env_server/server.py": [
{
"code": "reportArgumentType",
"range": {
"startColumn": 40,
"endColumn": 60,
"lineCount": 1
}
},
{
"code": "reportArgumentType",
"range": {
"startColumn": 28,
"endColumn": 42,
"lineCount": 1
}
}
],
"./positronic/simulator/env_server/tests/mujoco_env.py": [
{
"code": "reportArgumentType",
Expand Down Expand Up @@ -6364,16 +6328,6 @@
}
}
],
"./positronic/simulator/robolab/launcher.py": [
{
"code": "reportArgumentType",
"range": {
"startColumn": 24,
"endColumn": 42,
"lineCount": 1
}
}
],
"./positronic/simulator/robolab/make_fixture.py": [
{
"code": "reportMissingImports",
Expand Down
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ build

# Virtual environments
.venv
.venv-*
venv
env
ENV
Expand Down
4 changes: 4 additions & 0 deletions docker/CONTEXTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
| `positro/openpi` | OpenPI training and inference |
| `positro/dreamzero` | DreamZero inference (1+ GPU, H100 80GB recommended) |
| `positro/robolab` | RoboLab (Isaac Lab) eval — runs `positronic eval run`, which spawns the Isaac sim subprocess in-container; needs an RTX-class GPU |
| `positro/galaxea` | G0.5-DROID inference, internal non-commercial evaluation only; isolated Galaxea and Positronic Python environments |

Build and push all: `make push`

Galaxea is opt-in: `make build-galaxea`. Its evaluation-only image is excluded from
aggregate builds and pushes; see [the vendor README](../positronic/vendors/galaxea/README.md).

## References

- Service definitions and compose commands: `docker-compose.yml`
Expand Down
45 changes: 45 additions & 0 deletions docker/Dockerfile.galaxea
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Internal, non-commercial evaluation only. See positronic/vendors/galaxea/NOTICE and LICENSE-G0.5.
FROM ubuntu:22.04

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake git ca-certificates ffmpeg \
libgl1 libglib2.0-0 libsm6 libxext6 libturbojpeg \
&& rm -rf /var/lib/apt/lists/*

# Keep interpreter symlinks outside the host-mounted cache directories.
ENV UV_PYTHON_INSTALL_DIR=/opt/uv/python \
UV_LINK_MODE=copy \
UV_HTTP_TIMEOUT=600 \
NVIDIA_VISIBLE_DEVICES=all \
NVIDIA_DRIVER_CAPABILITIES=compute,utility

ARG GALAXEA_SHA=89f2322b4ad016e192437adc1a2c253b05bab246
RUN git clone https://github.com/OpenGalaxea/GalaxeaVLA.git /galaxea \
&& git -C /galaxea checkout ${GALAXEA_SHA}

WORKDIR /galaxea
COPY positronic/vendors/galaxea/requirements-inference.txt /galaxea/requirements-inference.txt
# Export versions without installing Galaxea's training and simulation dependencies.
RUN --mount=type=cache,target=/root/.cache/uv \
uv export --frozen --no-dev --no-emit-project --no-hashes --format requirements-txt \
--output-file /galaxea/constraints.txt \
&& uv venv --python 3.10 /galaxea/.venv \
&& uv pip install --python /galaxea/.venv/bin/python \
--index https://pypi.org/simple --default-index https://download.pytorch.org/whl/cu128 \
--index-strategy unsafe-best-match \
--constraint /galaxea/constraints.txt --requirement /galaxea/requirements-inference.txt

WORKDIR /positronic
COPY . /positronic
ENV UV_PROJECT_ENVIRONMENT=/opt/positronic-venv \
PYTHONPATH=/positronic
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev --python 3.13

LABEL org.opencontainers.image.description="G0.5-DROID for internal, non-commercial evaluation only" \
org.opencontainers.image.licenses="Apache-2.0 AND LicenseRef-G0.5-Community-1.0"

EXPOSE 8000
ENTRYPOINT ["/opt/positronic-venv/bin/python", "-m", "positronic.vendors.galaxea.server"]
31 changes: 22 additions & 9 deletions docker/Makefile
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
.PHONY: all build tag push clean prune help build-training tag-training push-training build-openpi tag-openpi push-openpi build-groot tag-groot push-groot build-dreamzero-base push-dreamzero-base build-dreamzero tag-dreamzero push-dreamzero build-robolab tag-robolab push-robolab nebius-login push-robolab-cr
.PHONY: build-galaxea tag-galaxea push-galaxea

# Image configuration
IMAGE_NAME_TRAINING := positro/positronic
IMAGE_NAME_OPENPI := positro/openpi
IMAGE_NAME_GROOT := positro/gr00t
IMAGE_NAME_DREAMZERO := positro/dreamzero
IMAGE_NAME_DREAMZERO_BASE := positro/dreamzero-base
IMAGE_NAME_OPENPI_BASE := positro/openpi-base
IMAGE_NAME_ROBOLAB := positro/robolab
IMAGE_NAME_GALAXEA := positro/galaxea

# Extract version from pyproject.toml (first literal version entry)
VERSION := $(shell sed -n 's/^version = "\([^"]*\)"/\1/p' ../pyproject.toml | head -n 1)

# Get git commit SHA (short)
GIT_SHA := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")

# Branch name sanitized for Docker tags (replace / with -)
# Docker tags cannot contain slashes.
BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-')

# IMAGE_TAG: branch name locally, overridable via `make push IMAGE_TAG=foo`
IMAGE_TAG ?= $(BRANCH)

REGISTRY_URL ?= docker.io

# Nebius Container Registry — opt-in path for an in-region pull from serverless
# jobs (the `push-*` targets above stay on Docker Hub and are unchanged). Override
# NEBIUS_REGISTRY for a different project/registry; set NEBIUS_PROFILE to use a
# Nebius publishing is opt-in for in-region pulls; default push targets use Docker Hub.
# Override NEBIUS_REGISTRY for a different project/registry; set NEBIUS_PROFILE to use a
# non-default `nebius` CLI profile (e.g. a service-account profile for headless
# CI). Auth goes through the nebius credential helper — no registry secret here.
NEBIUS_REGISTRY ?= cr.eu-north1.nebius.cloud/e00a0ahqzcp9x0xczz
NEBIUS_REGISTRY_HOST := $(firstword $(subst /, ,$(NEBIUS_REGISTRY)))
NEBIUS_PROFILE_FLAG := $(if $(NEBIUS_PROFILE),--profile $(NEBIUS_PROFILE),)

# Local build tags
LOCAL_TAG_TRAINING := $(IMAGE_NAME_TRAINING):local

# Base image tags (not parameterized — these are heavy foundational images)
Expand All @@ -52,6 +49,7 @@ help:
@echo ""
@echo "Targets:"
@echo " make build-training Build the training image"
@echo " make build-galaxea Build the internal non-commercial evaluation image"
@echo " make build Build training, openpi and groot images"
@echo ""
@echo " make tag-training Tag the training image (depends on build-training)"
Expand Down Expand Up @@ -99,6 +97,17 @@ build-robolab:
@echo "Building $(IMAGE_NAME_ROBOLAB)..."
docker build --platform linux/amd64 -f Dockerfile.robolab -t $(IMAGE_NAME_ROBOLAB):local ..

build-galaxea:
docker build --platform linux/amd64 -f Dockerfile.galaxea -t $(IMAGE_NAME_GALAXEA):local ..
Comment thread
vertix marked this conversation as resolved.

tag-galaxea: build-galaxea
docker tag $(IMAGE_NAME_GALAXEA):local $(IMAGE_NAME_GALAXEA):$(IMAGE_TAG)
docker tag $(IMAGE_NAME_GALAXEA):local $(IMAGE_NAME_GALAXEA):$(GIT_SHA)

push-galaxea: tag-galaxea
docker push $(IMAGE_NAME_GALAXEA):$(IMAGE_TAG)
docker push $(IMAGE_NAME_GALAXEA):$(GIT_SHA)

build: build-training build-openpi build-groot build-dreamzero build-robolab

tag-training: build-training
Expand Down Expand Up @@ -252,6 +261,7 @@ endif

all: push

# Optional image tags can be absent; removal errors must not stop attempts on the other tags.
clean:
@echo "Removing all local images..."
-docker rmi $(LOCAL_TAG_TRAINING)
Expand All @@ -270,7 +280,10 @@ clean:
-docker rmi $(IMAGE_NAME_ROBOLAB):local
-docker rmi $(IMAGE_NAME_ROBOLAB):$(IMAGE_TAG)
-docker rmi $(IMAGE_NAME_ROBOLAB):$(GIT_SHA)
@echo "All local images removed."
-docker rmi $(IMAGE_NAME_GALAXEA):local
-docker rmi $(IMAGE_NAME_GALAXEA):$(IMAGE_TAG)
-docker rmi $(IMAGE_NAME_GALAXEA):$(GIT_SHA)
@echo "Image cleanup attempts complete. Check the output for removal errors."

prune:
@echo "Pruning dangling and unused Docker images..."
Expand Down
9 changes: 9 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,12 @@ docker/build.sh

If you customize `docker-compose.yml` volumes, **do not bind-mount** your host `~/.local/share/uv` into `/root/.local/share/uv` for `positro/gr00t` images.
GR00T's `/.venv/bin/python` can be a symlink into the image's own uv-managed CPython under `/root/.local/share/uv/python/...`, and the bind mount can hide that target and cause `/.venv/bin/python` to fail with `ENOENT`.

## Galaxea: internal evaluation access

The `galaxea-server` service publishes port 8000 on the Docker host's localhost.
Use Docker Engine 28 or newer with default bridge networking. Remote DROID clients
connect through SSH forwarding; RoboLab uses `galaxea-server:8000` on the same
Compose network and Docker daemon. Start the server with `--service-ports --use-aliases`.
See the [Galaxea setup](../positronic/vendors/galaxea/README.md#start-the-server)
for the commands and internal, non-commercial usage conditions.
30 changes: 20 additions & 10 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ services:
image: positro/positronic:${IMAGE_TAG:-latest}
pull_policy: always

# Enable interactive terminal
stdin_open: true
tty: true

Expand All @@ -16,7 +15,6 @@ services:
count: all
capabilities: [compute, graphics, utility]

# Volume mounts
volumes:
- ${CACHE_ROOT:-${HOME}}/.cache:/root/.cache
- ${CACHE_ROOT:-${HOME}}/.aws:/root/.aws:ro
Expand All @@ -35,7 +33,6 @@ services:
positronic: &openpi-common
image: positro/openpi:${IMAGE_TAG:-latest}

# Enable interactive terminal
stdin_open: true
tty: true

Expand All @@ -48,7 +45,6 @@ services:
count: all
capabilities: [compute, graphics, utility]

# Volume mounts
volumes:
- ${CACHE_ROOT:-${HOME}}/.cache:/root/.cache
- ${CACHE_ROOT:-${HOME}}/.aws:/root/.aws:ro
Expand Down Expand Up @@ -164,7 +160,6 @@ services:
positronic-groot: &groot-common
image: positro/gr00t:${IMAGE_TAG:-latest}

# Enable interactive terminal
stdin_open: true
tty: true

Expand All @@ -177,7 +172,6 @@ services:
count: all
capabilities: [compute, graphics, utility]

# Volume mounts
volumes:
- ${CACHE_ROOT:-${HOME}}/.cache:/root/.cache
- ${CACHE_ROOT:-${HOME}}/.aws:/root/.aws:ro
Expand All @@ -200,7 +194,7 @@ services:
<<: *groot-common
container_name: groot-train
shm_size: 8g
ipc: host # Enable shared memory access for training
ipc: host
entrypoint: ["uv", "run", "--python", "3.13", "python", "-m", "positronic.vendors.gr00t.train"]

groot-server: &groot-server-common
Expand All @@ -213,11 +207,9 @@ services:
positronic-dreamzero: &dreamzero-common
image: positro/dreamzero:${IMAGE_TAG:-latest}

# Enable interactive terminal
stdin_open: true
tty: true

# GPU support
deploy:
resources:
reservations:
Expand All @@ -226,7 +218,6 @@ services:
count: all
capabilities: [compute, graphics, utility]

# Volume mounts
volumes:
- ${CACHE_ROOT:-${HOME}}/.cache:/root/.cache
- ${CACHE_ROOT:-${HOME}}/.aws:/root/.aws:ro
Expand Down Expand Up @@ -257,6 +248,25 @@ services:
ipc: host
entrypoint: ["uv", "run", "--python", "3.13", "python", "-m", "positronic.vendors.dreamzero.train"]

# Galaxea model use is restricted to internal, non-commercial evaluation; see vendors/galaxea/NOTICE.
galaxea-server:
image: positro/galaxea:${IMAGE_TAG:-latest}
init: true
shm_size: 8g
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [compute, utility]
volumes:
- ${CACHE_ROOT:-${HOME}}/.cache:/root/.cache
- ${CACHE_ROOT:-${HOME}}/.aws:/root/.aws:ro
- ${CACHE_ROOT:-${HOME}}/.cache/galaxea/checkpoints:/galaxea/checkpoints
ports:
- "127.0.0.1:8000:8000"

robolab-eval:
image: positro/robolab:${IMAGE_TAG:-latest}

Expand Down
Loading
Loading