Every year or so, I try to set up Docker with an NVIDIA GPU with different capabilities. Most of the tutorials seem to focus on the CUDA use case to serve the AI deep learning wave. Posts on enabling CUDA and OpenGL in the same container are less frequent.

Code and general notes

Below, you can find a docker-compose setup that currently works, which I use to make the code from my Ph.D. thesis more reproducible. It is intended for devcontainers, so code is mounted into the container workspace.

services:
  cuda-opengl:
    build:
      dockerfile: .devcontainer/Dockerfile
      context: ..
    volumes:
      - ..:/home/vscode/workspace:cached
      # GUI support
      - /tmp/.X11-unix:/tmp/.X11-unix
    environment:
      # GUI support
      DISPLAY: $DISPLAY
      # Use NVIDIA GPU for rendering
      __NV_PRIME_RENDER_OFFLOAD: 1
      __GLX_VENDOR_LIBRARY_NAME: nvidia
      NVIDIA_DRIVER_CAPABILITIES: compute,utility,graphics,display
    deploy:
      resources:
        reservations:
          devices:
            - capabilities: [gpu]
    # Keep the container running so VS Code can attach
    tty: true

Most tutorials tell you how to enable CUDA or OpenGL in  docker run. Using a docker-compose file makes things much clearer and more maintainable.

The original version from the link above includes some configurations that enable OpenGL in the Windows subsystem for Linux (WSL2). At the time of writing, WSL2 does not support CUDA and OpenGL interop due to the Direct3D layer in between.

CUDA support

First, you need a Dockerfile that is based on one of the docker.io/nvidia/cuda images. Second, you need to install the NVIDIA container toolkit.

In the docker-compose file, NVIDIA GPUs are added in the deploy section which mimicks docker run --gpus all. Besides that, NVIDIA_DRIVER_CAPABILITIES enables CUDA via compute and tools like nvidia-smi via utility.

OpenGL support

The first part is making the display available in the container. We have to mount the X11 sockets in /tmp/.X11-unix and set the DISPLAY variable correctly. Next, we have to make sure that the NVIDIA GPU is used for rendering to enable CUDA-OpenGL interop by setting __NV_PRIME_RENDER_OFFLOAD and __GLX_VENDOR_LIBRARY_NAME. We also need to enable the corresponding NVIDIA_DRIVER_CAPABILITIES via graphics and display.