diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..7e39904a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.github +docs +**/__pycache__ +*.egg-info +.pytest_cache +Dockerfile diff --git a/Dockerfile b/Dockerfile index 9b9cb002..6d583bbd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,34 +23,63 @@ FROM ubuntu:22.04 ARG DEBIAN_FRONTEND="noninteractive" -ENV LIBGL_ALWAYS_INDIRECT=1 -ENV NVIDIA_VISIBLE_DEVICES \ - ${NVIDIA_VISIBLE_DEVICES:-all} -ENV NVIDIA_DRIVER_CAPABILITIES \ - ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics +# Render headless by default. Override at runtime for GUI use, e.g.: +# docker run -e QT_QPA_PLATFORM=xcb -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix ... +ENV QT_QPA_PLATFORM=offscreen +# System libs: OpenGL runtime (pyqtgraph/PyOpenGL), Qt6 runtime (PyQt6 wheels), +# and the Qt6 xcb platform plugin libs for running with a forwarded X display. RUN apt-get update --fix-missing && \ - apt-get install -y \ + apt-get install -y --no-install-recommends \ python3-dev \ python3-pip \ git \ build-essential \ - libgl1-mesa-dev \ - mesa-utils \ - libglu1-mesa-dev \ - fontconfig \ - libfreetype6-dev + libgl1 \ + libegl1 \ + libopengl0 \ + libglu1-mesa \ + libglib2.0-0 \ + libfontconfig1 \ + libdbus-1-3 \ + libsm6 \ + libxrender1 \ + libxext6 \ + libxkbcommon-x11-0 \ + libxcb-cursor0 \ + libxcb-icccm4 \ + libxcb-image0 \ + libxcb-keysyms1 \ + libxcb-randr0 \ + libxcb-render-util0 \ + libxcb-shape0 \ + libxcb-xkb1 && \ + rm -rf /var/lib/apt/lists/* RUN pip3 install --upgrade pip -RUN pip3 install PyOpenGL \ - PyOpenGL_accelerate -RUN mkdir /f1tenth_gym COPY . /f1tenth_gym -RUN cd /f1tenth_gym && \ - pip3 install -e . +# arm64: PyQt6 6.7.1 is the newest release with an aarch64 wheel compatible +# with Ubuntu 22.04's glibc 2.35 — newer ones need glibc >= 2.39, so pip +# falls back to the sdist and fails looking for qmake (seen on Apple +# Silicon). x86_64 is unaffected by the constraint. +RUN echo 'pyqt6 == 6.7.1; platform_machine == "aarch64"' > /tmp/pip-constraints.txt && \ + cd /f1tenth_gym && \ + pip3 install -c /tmp/pip-constraints.txt -e . + +# Smoke test: step the env and render a frame offscreen. Also bakes the +# default track (downloaded on first use) into the image. +RUN python3 -c "\ +import gymnasium as gym; \ +import f1tenth_gym; \ +env = gym.make('f1tenth_gym:f1tenth-v0', render_mode='rgb_array'); \ +env.reset(); \ +[env.step(env.action_space.sample()) for _ in range(50)]; \ +frame = env.render(); \ +assert frame is not None and frame.size > 0; \ +print('smoke test OK')" WORKDIR /f1tenth_gym diff --git a/README.md b/README.md index 53afd3ac..cc11084d 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,17 @@ python examples/waypoint_follow.py ### Using Docker -A Dockerfile is also provided with support for the GUI with nvidia-docker (nvidia GPU required): +A Dockerfile is also provided. The image renders headless by default (Qt offscreen), no GPU required: ```bash -docker build -t f1tenth_gym_container -f Dockerfile . -docker run --gpus all -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix f1tenth_gym_container +docker build -t f1tenth_gym . +docker run -it f1tenth_gym +# inside the container: +python3 examples/waypoint_follow.py +``` + +To render to a display instead, forward your X server and override the Qt platform: +```bash +docker run -it -e QT_QPA_PLATFORM=xcb -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix f1tenth_gym ``` ## Citing