diff --git a/.github/workflows/sleap_vscode_tunnel_production.yml b/.github/workflows/sleap_vscode_tunnel_production.yml new file mode 100644 index 0000000..714f3bc --- /dev/null +++ b/.github/workflows/sleap_vscode_tunnel_production.yml @@ -0,0 +1,69 @@ +name: Build and Push sleap-vscode-tunnel (Production Workflow) + +# Run on push to main branch after testing is complete +on: + push: + branches: + - main + paths: + - sleap_vscode_tunnel/** # Only run on changes to sleap_vscode_tunnel + - .github/workflows/sleap_vscode_tunnel_production.yml # Only run on changes to this workflow + +jobs: + build: + runs-on: ubuntu-latest # Only build on Ubuntu for now since Docker is not available on macOS runners + strategy: + matrix: + platform: [linux/amd64] # Only build amd64 for now + max-parallel: 2 # Build both architectures in parallel (if more than one) + outputs: + git_sha: ${{ steps.get_sha.outputs.sha }} + sanitized_platform: ${{ steps.sanitize_platform.outputs.sanitized_platform }} + steps: + - name: Checkout code + # https://github.com/actions/checkout + uses: actions/checkout@v4 + + - name: Get Git SHA + id: get_sha + run: echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + - name: Debug Git SHA + run: echo "Git SHA ${{ steps.get_sha.outputs.sha }}" + + # Generate a sanitized platform string with slashes replaced by dashes + - name: Sanitize platform name + id: sanitize_platform + run: | + sanitized_platform="${{ matrix.platform }}" # Copy platform value + sanitized_platform="${sanitized_platform/\//-}" # Replace / with - + echo "sanitized_platform=$sanitized_platform" >> $GITHUB_OUTPUT + + - name: Set up Docker Buildx + # https://github.com/docker/setup-buildx-action + uses: docker/setup-buildx-action@v3 + with: + driver: docker-container # Use a container driver for Buildx (default) + + - name: Log in to Docker Hub + # https://github.com/docker/login-action + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push Docker image + # https://github.com/docker/build-push-action + uses: docker/build-push-action@v6 + with: + context: ./sleap_vscode_tunnel # Build context wrt the root of the repository + file: ./sleap_vscode_tunnel/Dockerfile # Path to Dockerfile wrt the root of the repository + platforms: ${{ matrix.platform }} + push: true # Push the image to Docker Hub + # Tags for the production images, including the "latest" tag + tags: | + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:latest + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }} + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }}-nvidia-cuda-11.3.1-cudnn8-runtime-ubuntu20.04 + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }}-sleap-1.3.4 + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }}-${{ steps.get_sha.outputs.sha }} \ No newline at end of file diff --git a/.github/workflows/sleap_vscode_tunnel_test.yml b/.github/workflows/sleap_vscode_tunnel_test.yml new file mode 100644 index 0000000..2a9ee71 --- /dev/null +++ b/.github/workflows/sleap_vscode_tunnel_test.yml @@ -0,0 +1,68 @@ +name: Build and Push sleap-vscode-tunnel (Test Workflow) + +# Run on push to branches other than main for sleap_vscode_tunnel +on: + push: + branches-ignore: + - main + paths: + - sleap_vscode_tunnel/** # Only run on changes to sleap_vscode_tunnel + - .github/workflows/sleap_vscode_tunnel_test.yml # Only run on changes to this workflow + +jobs: + build: + runs-on: ubuntu-latest # Only build on Ubuntu for now since Docker is not available on macOS runners + strategy: + matrix: + platform: [linux/amd64] # Only build amd64 for now + max-parallel: 2 # Build both architectures in parallel (if more than one) + outputs: + git_sha: ${{ steps.get_sha.outputs.sha }} + sanitized_platform: ${{ steps.sanitize_platform.outputs.sanitized_platform }} + steps: + - name: Checkout code + # https://github.com/actions/checkout + uses: actions/checkout@v4 + + - name: Get Git SHA + id: get_sha + run: echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + - name: Debug Git SHA + run: echo "Git SHA ${{ steps.get_sha.outputs.sha }}" + + # Generate a sanitized platform string with slashes replaced by dashes + - name: Sanitize platform name + id: sanitize_platform + run: | + sanitized_platform="${{ matrix.platform }}" # Copy platform value + sanitized_platform="${sanitized_platform/\//-}" # Replace / with - + echo "sanitized_platform=$sanitized_platform" >> $GITHUB_OUTPUT + + - name: Set up Docker Buildx + # https://github.com/docker/setup-buildx-action + uses: docker/setup-buildx-action@v3 + with: + driver: docker-container # Use a container driver for Buildx (default) + + - name: Log in to Docker Hub + # https://github.com/docker/login-action + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push Docker image + # https://github.com/docker/build-push-action + uses: docker/build-push-action@v6 + with: + context: ./sleap_vscode_tunnel # Build context wrt the root of the repository + file: ./sleap_vscode_tunnel/Dockerfile # Path to Dockerfile wrt the root of the repository + platforms: ${{ matrix.platform }} + push: true # Push the image to Docker Hub + # Tags all include "-test" to differentiate from production images + tags: | + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }}-test + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }}-nvidia-cuda-11.3.1-cudnn8-runtime-ubuntu20.04-test + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }}-sleap-1.3.4-test + ${{ vars.DOCKERHUB_USERNAME }}/sleap-vscode-tunnel:${{ steps.sanitize_platform.outputs.sanitized_platform }}-${{ steps.get_sha.outputs.sha }}-test diff --git a/README.md b/README.md index 602ecf9..a98b8ba 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,113 @@ -# sleap-cuda-container - - -## Description -This repo contains a DockerFile for a lightweight container (~2.79 GB) with the PyPI installation of SLEAP and all of its dependencies. The container repository is located at [https://hub.docker.com/repository/docker/eberrigan/sleap-cuda/general](https://hub.docker.com/repository/docker/eberrigan/sleap-cuda/general). - -The base image used is [nvidia/cuda:11.3.1-cudnn8-runtime-ubuntu20.04](https://hub.docker.com/layers/nvidia/cuda/11.3.1-cudnn8-runtime-ubuntu20.04/images/sha256-025a321d3131b688f4ac09d80e9af6221f2d1568b4f9ea6e45a698beebb439c0). -- The Dockerfile is located at `docker/Dockerfile`. -- The repo has CI set up in `.github/workflows` for building and pushing the image when making changes. - - The workflow uses the linux/amd64 platform to build. -- `.devcontainer/devcontainer.json` is convenient for developing inside a container made with the DockerFile using Visual Studio Code. -- Test data for training is located in `tests/data`. - - -## Installation - -**Make sure to have Docker Daemon running first** - - -You can pull the image if you don't have it built locally, or need to update the latest, with - -``` +# SLEAP CUDA Container Repository + +This repository provides multiple Docker configurations for running **SLEAP** (a machine learning-based tool for animal pose estimation) in different environments, leveraging GPU support and Ubuntu. These configurations enable different ways to interact with the containerized SLEAP environment, including VNC and VS Code Tunnels. + +--- + +## Repository Structure + +The repository is organized as follows: + +``` +sleap-cuda-container (repo) +│ +├── .github +├── sleap_cuda +│ ├── README.md +│ ├── Dockerfile +│ ├── .dockerignore +│ ├── .devcontainer +│ +├── sleap_vnc_connect +│ ├── README.md +│ ├── Dockerfile +│ ├── .dockerignore +│ ├── .devcontainer +│ +├── sleap_vscode_tunnel +│ ├── README.md +│ ├── Dockerfile +│ ├── .dockerignore +│ ├── .devcontainer +│ +├── tests +├── README.md +├── .gitignore +└── LICENSE +``` + +### Subfolders and Containers + +- **`sleap_cuda/`**: + - Contains the base image for SLEAP with GPU support and Ubuntu. + - This image is the foundation for other container configurations. + - **[Docker Hub Link](https://hub.docker.com/repository/docker/eberrigan/sleap-cuda/general)**. + +- **`sleap_vnc_connect/`**: + - Adds a **VNC server** to the base image, allowing you to connect to the container using a local VNC client. + - Useful for graphical interaction with the SLEAP GUI. + - See the `README.md` in this folder for setup and connection instructions. + +- **`sleap_vscode_tunnel/`**: + - Adds the **VS Code CLI** for establishing a remote tunnel connection to the container. + - Enables headless interaction with the container through VS Code. + - Note: **VS Code Tunnels do not yet support port forwarding**, so graphical applications (like the SLEAP GUI) cannot be used with this container. + +- **`tests/`**: + - Contains test scripts for validating the functionality of the Docker configurations. + +--- + +## Running the Containers + +### 1. **Base SLEAP CUDA Container** +To use the base container: +```bash docker pull eberrigan/sleap-cuda:latest ``` -## Usage +### 2. **SLEAP VNC Connect** +The `sleap_vnc_connect` container starts a **VNC server**, enabling a graphical interface for SLEAP. -Then, to run the image with gpus interactively: +1. **Build and Run**: + ```bash + docker build -t sleap-vnc ./sleap_vnc_connect + docker run --rm -it -p 5901:5901 --gpus all sleap-vnc + ``` -``` -docker run --gpus all -it eberrigan/sleap-cuda:latest bash -``` +2. **Connect to the VNC Server**: + - Use a VNC client and connect to `localhost:5901`. + - Ensure your display environment variables are correctly set. -and test with +### 3. **SLEAP VS Code Tunnel** +The `sleap_vscode_tunnel` container allows **remote development** using VS Code tunnels. -``` -python -c "import sleap; sleap.versions()" && nvidia-smi -``` +1. **Build and Run**: + ```bash + docker build -t sleap-tunnel ./sleap_vscode_tunnel + docker run --rm -it --gpus all sleap-tunnel + ``` -In general, use the syntax +2. **Connect to the Tunnel**: + - The VS Code CLI in the container starts a tunnel. + - Use the provided tunnel URL in VS Code to connect and work remotely. -``` -docker run -v /path/on/host:/path/in/container [other options] image_name [command] -``` +--- -Note that host paths are absolute. +## Notes and Limitations +- **Remote Tunnels**: + - VS Code Remote Tunnels do not currently support port forwarding. As a result, graphical applications like the SLEAP GUI cannot run in this container. -Use this syntax to give host permissions to mounted volumes -``` -docker run -u $(id -u):$(id -g) -v /your/host/directory:/container/directory [options] your-image-name [command] -``` +- **VNC**: + - The VNC Connect container requires port `5901` to be exposed. Use the `-p` flag to map this port when running the container. -``` -docker run -u $(id -u):$(id -g) -v ./tests/data:/workspace/tests/data --gpus all -it eberrigan/sleap-cuda:latest bash -``` +- **X11 Forwarding**: + - If graphical interaction is required over an SSH connection, ensure proper X11 forwarding is set up. -Test: +--- -``` - python3 -c "import sleap; print('SLEAP version:', sleap.__version__)" - nvidia-smi # Check that the GPUs are disvoerable - ps aux | grep Xtightvnc # Check that the VNC server is running - sleap-train "tests/data/initial_config.json" "tests/data/dance.mp4.labels.slp" --video-paths "tests/data/dance.mp4" -``` - -**Notes:** - -- The `eberrigan/sleap-cuda` is the Docker registry where the images are pulled from. This is only used when pulling images from the cloud, and not necesary when building/running locally. -- `-it` ensures that you get an interactive terminal. The `i` stands for interactive, and `t` allocates a pseudo-TTY, which is what allows you to interact with the bash shell inside the container. -- The `-v` or `--volume` option mounts the specified directory with the same level of access as the directory has on the host. -- `bash` is the command that gets executed inside the container, which in this case is to start the bash shell. -- Order of operations is 1. Pull (if needed): Get a pre-built image from a registry. 2. Run: Start a container from an image. - -## Contributing - -- Use the `devcontainer.json` to open the repo in a dev container using VS Code. - - There is some test data in the `tests` directory that will be automatically mounted for use since the working directory is the workspace. - - Rebuild the container when you make changes using `Dev Container: Rebuild Container`. - -- Please make a new branch, starting with your name, with any changes, and request a reviewer before merging with the main branch since this image will be used by others. -- Please document using the same conventions (docstrings for each function and class, typing-hints, informative comments). -- Tests are written in the pytest framework. Data used in the tests are defined as fixtures in `tests/fixtures/data.py` (https://docs.pytest.org/en/6.2.x/reference.html#fixtures-api). - - -## Build -To build and push via automated CI, just push changes to a branch. -- Pushes to `main` result in an image with the tag `latest`. -- Pushes to other branches have tags with `-test` appended. -- See `.github/workflows` for testing and production workflows. - -To test `test` images locally use after pushing the `test` images via CI: - -``` -docker pull eberrigan/sleap-cuda:linux-amd64-test -``` - -then - -``` -docker run -v ./tests/data:/workspace/tests/data --gpus all -it eberrigan/sleap-cuda:linux-amd64-test bash -``` - -To build locally for testing you can use the command: - -``` -docker build --platform linux/amd64 ./docker -``` +## License +This repository is licensed under the **MIT License**. See the `LICENSE` file for more details. -## Support -contact Elizabeth at eberrigan@salk.edu +For additional questions or issues, please open an issue in this repository. \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/sleap_cuda/.devcontainer/devcontainer.json similarity index 72% rename from .devcontainer/devcontainer.json rename to sleap_cuda/.devcontainer/devcontainer.json index 7793765..ad57836 100644 --- a/.devcontainer/devcontainer.json +++ b/sleap_cuda/.devcontainer/devcontainer.json @@ -1,18 +1,24 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile { - "name": "Existing Dockerfile", + "name": "SLEAP VNC Container", "build": { - // Sets the run context to the subfolder. - "context": "../sleap_cuda", - // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. - "dockerfile": "../sleap_cuda/Dockerfile" - }, - "features": { + "context": "..", + "dockerfile": "../Dockerfile" }, "runArgs": [ - "--gpus", "all" - ] + "--gpus=all" + ], + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash" + } + } + }, + "postCreateCommand": "echo 'Devcontainer ready for use!'", + "remoteUser": "root" + } // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, @@ -28,4 +34,3 @@ // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "devcontainer" -} diff --git a/sleap_vnc_connect/.devcontainer/devcontainer.json b/sleap_vnc_connect/.devcontainer/devcontainer.json new file mode 100644 index 0000000..67d7c44 --- /dev/null +++ b/sleap_vnc_connect/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +{ + "name": "SLEAP VNC Container", + "build": { + "context": "..", + "dockerfile": "../Dockerfile" + }, + "forwardPorts": [5901], + "runArgs": [ + "--gpus=all", + "-p", "5901:5901" + ], + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash" + } + } + }, + "postCreateCommand": "echo 'Devcontainer ready for use!'", + "remoteUser": "root" + } + \ No newline at end of file diff --git a/sleap_vnc_connect/Dockerfile b/sleap_vnc_connect/Dockerfile index 85b34fb..59cca0c 100644 --- a/sleap_vnc_connect/Dockerfile +++ b/sleap_vnc_connect/Dockerfile @@ -1,47 +1,16 @@ -# Base image with GPU support -FROM nvidia/cuda:11.3.1-cudnn8-runtime-ubuntu20.04 +# Base image with SLEAP and GPU support +# https://hub.docker.com/repository/docker/eberrigan/sleap-cuda/general +FROM eberrigan/sleap-cuda:latest -# Set non-interactive mode -ENV DEBIAN_FRONTEND=noninteractive - -ENV USER=root - -# Install dependencies -# opencv requires opengl https://github.com/conda-forge/opencv-feedstock/issues/401 -# https://medium.com/@gustav0.lewin/how-to-make-a-docker-container-with-vnc-access-f607958141ae -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - libgl1-mesa-glx \ - libglapi-mesa \ - libegl-mesa0 \ - libegl1 \ - libopengl0 \ - libglib2.0-0 \ - libfontconfig1 \ - libgssapi-krb5-2 \ - libdbus-1-3 \ - libx11-xcb1 \ - libxkbcommon-x11-0 \ +# Install required tools for VNC server +RUN apt-get update && apt-get install -y --no-install-recommends \ xfce4 \ xfce4-goodies \ tightvncserver \ dbus-x11 \ xfonts-base \ - x11-xserver-utils \ - x11-utils \ autocutsel \ - python3-pip && \ - python3 -m pip install --upgrade pip && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -# Install SLEAP -RUN pip install --no-cache-dir sleap[pypi]==1.3.4 - -ENV NVIDIA_DRIVER_CAPABILITIES=all - -# Set QT debug environment variable to help debug issues with Qt plugins -ENV QT_DEBUG_PLUGINS=1 + && rm -rf /var/lib/apt/lists/* # Setup VNC server RUN mkdir /root/.vnc && \ diff --git a/sleap_vnc_connect/README.md b/sleap_vnc_connect/README.md index 42eea0c..da608bb 100644 --- a/sleap_vnc_connect/README.md +++ b/sleap_vnc_connect/README.md @@ -1,11 +1,12 @@ # sleap-vnc-connect -The SLEAP GUI will not open in the VNC server and I do not know why! VNC connection works. +The SLEAP GUI will not open in the VNC server and I do not know why! VNC connection works. Something with the X server. ## Description -This repo contains a DockerFile for a lightweight container (~2.79 GB) with the PyPI installation of SLEAP and all of its dependencies. The container repository is located at [https://hub.docker.com/repository/docker/eberrigan/sleap-vnc-connect/general](https://hub.docker.com/repository/docker/eberrigan/sleap-vnc-connect/general). +This repo contains a DockerFile for a lightweight container (~2.79 GB) with the PyPI installation of SLEAP and all of its dependencies and a VNC server. The VNC server can be connected to using port 5901. +The container repository is located at [https://hub.docker.com/repository/docker/eberrigan/sleap-vnc-connect/general](https://hub.docker.com/repository/docker/eberrigan/sleap-vnc-connect/general). -The base image used is [nvidia/cuda:11.3.1-cudnn8-runtime-ubuntu20.04](https://hub.docker.com/layers/nvidia/cuda/11.3.1-cudnn8-runtime-ubuntu20.04/images/sha256-025a321d3131b688f4ac09d80e9af6221f2d1568b4f9ea6e45a698beebb439c0). +The base image used is [eberrigan/sleap-cuda:latest](https://hub.docker.com/layers/eberrigan/sleap-cuda/latest/images/sha256-9cc93c86cc60d0f8e357bf58c2901d9b29a509c70ae16ed90ea56ac6d33418e7?context=repo). - The Dockerfile is located at `docker/Dockerfile`. - The repo has CI set up in `.github/workflows` for building and pushing the image when making changes. - The workflow uses the linux/amd64 platform to build. @@ -26,10 +27,10 @@ docker pull eberrigan/sleap-vnc-connect:latest ## Usage -Then, to run the image with gpus interactively: +Then, to run the image with gpus interactively and mapping port 5901, which is exposed in the container, to port 5901 on a VNC client ``` -docker run --gpus all -it eberrigan/sleap-vnc-connect:latest bash +docker run --gpus all -it -p 5901:5901 eberrigan/sleap-vnc-connect:latest bash ``` and test with @@ -53,15 +54,16 @@ docker run -u $(id -u):$(id -g) -v /your/host/directory:/container/directory [op ``` ``` -docker run -u $(id -u):$(id -g) -v ./tests/data:/workspace/tests/data --gpus all -it eberrigan/sleap-vnc-connect:latest bash +docker run -u $(id -u):$(id -g) -v ./tests/data:/workspace/tests/data --gpus all -it -p 5901:5901 eberrigan/sleap-vnc-connect:latest bash ``` Test: ``` python3 -c "import sleap; print('SLEAP version:', sleap.__version__)" - nvidia-smi # Check that the GPUs are disvoerable + nvidia-smi # Check that the GPUs are discoverable ps aux | grep Xtightvnc # Check that the VNC server is running + echo $DISPLAY # Check display environment variable is :1 sleap-train "tests/data/initial_config.json" "tests/data/dance.mp4.labels.slp" --video-paths "tests/data/dance.mp4" ``` @@ -71,12 +73,121 @@ Test: - `-it` ensures that you get an interactive terminal. The `i` stands for interactive, and `t` allocates a pseudo-TTY, which is what allows you to interact with the bash shell inside the container. - The `-v` or `--volume` option mounts the specified directory with the same level of access as the directory has on the host. - `bash` is the command that gets executed inside the container, which in this case is to start the bash shell. +- The `--rm` flag in a docker run command automatically removes the container when it stops. This is useful for running temporary or one-time containers without cluttering your Docker environment with stopped containers. +- The `-p 5901:5901` flag in a Docker run command maps a port on the host machine to a port inside the container. + +``` +-p [host-port]:[container-port] +``` + +`host-port`: The port number on the host machine (your local computer or server). +`container-port`: The port number inside the Docker container. +In this case, 5901 is mapped both inside and outside the container. + - Order of operations is 1. Pull (if needed): Get a pre-built image from a registry. 2. Run: Start a container from an image. +## Connect from a VNC Client + +Here's how you can structure the **README** to explain connecting to the VNC server inside the container: + +--- + +# Connecting to the VNC Server in the SLEAP Container + +This guide explains how to connect to the VNC server running inside the SLEAP container to access the graphical user interface (GUI). + +## Prerequisites + +1. **VNC Viewer**: Install a VNC viewer such as [TigerVNC](https://tigervnc.org/), [RealVNC](https://www.realvnc.com/), or [TightVNC](https://www.tightvnc.com/). +2. **Docker Setup**: + - Ensure Docker is installed and running on your system. + - The container is started with the `-p 5901:5901` port mapping. + +--- + +## Steps to Connect to the VNC Server + +### 1. Start the Container + +Start the container with the necessary port mapping to expose the VNC server on port `5901`: + +```bash +docker run -it --rm \ + -p 5901:5901 \ + --gpus=all \ + your-container-name +``` + +> **Note:** If you're using a Dev Container setup, the port mapping is already included in the configuration. + +--- + +### 2. Find the Host Machine's IP Address + +- If you are running the container locally: + - Use `localhost` or `127.0.0.1` to connect to the VNC server. + +- If the container is running on a remote machine: + - Find the machine's public or internal IP address. + - Use the following command on the remote machine: + ```bash + hostname -I + ``` + - Note the first IP address listed. + +--- + +### 3. Open the VNC Viewer + +1. Launch your VNC Viewer application. +2. Enter the following connection address: + ``` + :5901 + ``` + Replace `` with: + - `127.0.0.1` if running locally. + - The remote machine's IP address if connecting remotely. + +3. When prompted, enter the VNC password. This is configured inside the container. + +--- + +### 4. Access the GUI + +Once connected, you'll see the desktop environment configured in the container (e.g., XFCE). You can now open and use GUI-based applications such as `sleap-label`. + +--- + +## Troubleshooting + +1. **Cannot Connect to VNC Server**: + - Ensure the container is running and the `5901` port is correctly mapped. + - Verify the IP address is correct and reachable. + - Check that the VNC server inside the container is running. + +2. **Black Screen**: + - Ensure the desktop environment (e.g., XFCE) is correctly installed and configured. + +3. **Firewall Issues**: + - Ensure port `5901` is not blocked by a firewall (especially on remote setups). + +--- + +Would you like further customization or additions to this README? + +**Run.AI GPU Cluster** + +The ports can be forwarded to a localhost when running the container on RunAI using this documentation [walkthrough-build-ports](https://docs.run.ai/v2.19/Researcher/Walkthroughs/walkthrough-build-ports/). + +``` +# Connecting to container on RunAI +runai describe job +runai port-forward --port 5901:5901 +``` + ## Contributing -- Use the `devcontainer.json` to open the repo in a dev container using VS Code. - - There is some test data in the `tests` directory that will be automatically mounted for use since the working directory is the workspace. +- Use the `devcontainer.json` to open the folder `sleap_vnc_connect` in a dev container using VS Code. - Rebuild the container when you make changes using `Dev Container: Rebuild Container`. - Please make a new branch, starting with your name, with any changes, and request a reviewer before merging with the main branch since this image will be used by others. @@ -99,13 +210,13 @@ docker pull eberrigan/sleap-vnc-connect:linux-amd64-test then ``` -docker run -v ./tests/data:/workspace/tests/data --gpus all -it eberrigan/sleap-vnc-connect:linux-amd64-test bash +docker run -v ./tests/data:/workspace/tests/data --gpus all -p 5901:5901 -it eberrigan/sleap-vnc-connect:linux-amd64-test bash ``` To build locally for testing you can use the command: ``` -docker build --platform linux/amd64 ./docker +docker build --platform linux/amd64 . ``` ## Support diff --git a/sleap_vscode_tunnel/.devcontainer/devcontainer.json b/sleap_vscode_tunnel/.devcontainer/devcontainer.json new file mode 100644 index 0000000..68dae55 --- /dev/null +++ b/sleap_vscode_tunnel/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +{ + "name": "SLEAP VSCode Remote Tunnel Container", + "build": { + "context": "..", + "dockerfile": "../Dockerfile" + }, + "runArgs": [ + "--gpus=all" + ], + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash" + } + } + }, + "postCreateCommand": "echo 'Devcontainer ready for use!'", + "remoteUser": "root" + } + \ No newline at end of file diff --git a/sleap_vscode_tunnel/.dockerignore b/sleap_vscode_tunnel/.dockerignore new file mode 100644 index 0000000..8a75ad2 --- /dev/null +++ b/sleap_vscode_tunnel/.dockerignore @@ -0,0 +1,19 @@ +# Ignore Python cache +__pycache__/ +*.pyc +*.pyo + +# Ignore virtual environments +env/ +venv/ + +# Ignore version control and logs +.git/ +*.log + +# Ignore Docker build artifacts +docker/*.tmp + +README.md +.gitignore +terraform/* \ No newline at end of file diff --git a/sleap_vscode_tunnel/Dockerfile b/sleap_vscode_tunnel/Dockerfile new file mode 100644 index 0000000..35ccb72 --- /dev/null +++ b/sleap_vscode_tunnel/Dockerfile @@ -0,0 +1,28 @@ +# Base image with SLEAP and GPU support +# https://hub.docker.com/repository/docker/eberrigan/sleap-cuda/general +FROM eberrigan/sleap-cuda:latest + +# Install required tools +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + tar \ + && rm -rf /var/lib/apt/lists/* + +# Install VS Code CLI +RUN curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz && \ + tar -xf vscode_cli.tar.gz -C /usr/local/bin && \ + rm vscode_cli.tar.gz + +# Add VS Code CLI to PATH +ENV PATH="/usr/local/bin:$PATH" + +# Set the working directory in the container +WORKDIR /app + +# Add a script to run the VS Code tunnel +# https://code.visualstudio.com/docs/remote/tunnels#_using-the-code-cli +RUN echo "#!/bin/bash\n\n# Start VS Code tunnel\ncode tunnel --accept-server-license-terms" > /app/start-tunnel.sh && \ + chmod +x /app/start-tunnel.sh + +# Start VS Code tunnel +ENTRYPOINT ["/app/start-tunnel.sh"] \ No newline at end of file diff --git a/sleap_vscode_tunnel/README.md b/sleap_vscode_tunnel/README.md new file mode 100644 index 0000000..3317a5b --- /dev/null +++ b/sleap_vscode_tunnel/README.md @@ -0,0 +1,118 @@ +# sleap-vscode-tunnel + +This works well to develop in VS Code remotely with SLEAP installed and use the CLI. Unfortunately, port forwarding only works to expose locally-running service so that the GUI cannot be opened on the remote machine. +[How do I forward local services if I'm connected to a remote machine?](https://code.visualstudio.com/docs/editor/port-forwarding#_how-do-i-forward-local-services-if-im-connected-to-a-remote-machine) + +## Description +This repo contains a DockerFile for a lightweight container (~2.79 GB) with the PyPI installation of SLEAP and all of its dependencies. The container repository is located at [https://hub.docker.com/repository/docker/eberrigan/sleap-vscode-tunnel/general](https://hub.docker.com/repository/docker/eberrigan/sleap-vscode-tunnel/general). + +The base image used is [eberrigan/sleap-cuda:latest](https://hub.docker.com/layers/eberrigan/sleap-cuda/latest/images/sha256-9cc93c86cc60d0f8e357bf58c2901d9b29a509c70ae16ed90ea56ac6d33418e7?context=repo). +- The Dockerfile is located at `docker/Dockerfile`. +- The repo has CI set up in `.github/workflows` for building and pushing the image when making changes. + - The workflow uses the linux/amd64 platform to build. +- `.devcontainer/devcontainer.json` is convenient for developing inside a container made with the DockerFile using Visual Studio Code. + + +## Installation + +**Make sure to have Docker Daemon running first** + +You can pull the image if you don't have it built locally, or need to update the latest, with + +``` +docker pull eberrigan/sleap-vscode-tunnel:latest +``` + +## Usage + +Then, to run the image with gpus interactively: + +``` +docker run --gpus all -it eberrigan/sleap-vscode-tunnel:latest bash +``` + +and test with + +``` +python -c "import sleap; sleap.versions()" && nvidia-smi +``` + +In general, use the syntax + +``` +docker run -v /path/on/host:/path/in/container [other options] image_name [command] +``` + +Note that host paths are absolute. + +Use this syntax to give host permissions to mounted volumes +``` +docker run -u $(id -u):$(id -g) -v /your/host/directory:/container/directory [options] your-image-name [command] +``` + +``` +docker run -u $(id -u):$(id -g) -v ./tests/data:/tests/data --gpus all -it eberrigan/sleap-vscode-tunnel:latest bash +``` + +Test: + +``` + python3 -c "import sleap; print('SLEAP version:', sleap.__version__)" + nvidia-smi # Check that the GPUs are discoverable + sleap-train "tests/data/initial_config.json" "tests/data/dance.mp4.labels.slp" --video-paths "tests/data/dance.mp4" +``` + +**Notes:** + +- The `eberrigan/sleap-vscode-tunnel` is the Docker registry where the images are pulled from. This is only used when pulling images from the cloud, and not necesary when building/running locally. +- `-it` ensures that you get an interactive terminal. The `i` stands for interactive, and `t` allocates a pseudo-TTY, which is what allows you to interact with the bash shell inside the container. +- The `-v` or `--volume` option mounts the specified directory with the same level of access as the directory has on the host. +- `bash` is the command that gets executed inside the container, which in this case is to start the bash shell. +- Order of operations is 1. Pull (if needed): Get a pre-built image from a registry. 2. Run: Start a container from an image. + +## Connect to Remote Container with VS Code Remote Tunnel + +Documentation for VS Code Remote Tunnels is [here](https://code.visualstudio.com/docs/remote/tunnels). + +1. Run the container on your remote machine. + - The tunnel will be started in the container. +2. Check the logs of your running container for directions to authenticate using Github. + - Should see something like `To grant access to the server, please log into https://github.com/login/device and use code 2346-530B`. +3. Once authenticated, the logs should say `Creating tunnel with the name: `. You can connect to the container using the web address, where the web version of VS Code will be displayed in your containers environment, or using VS [Remote Tunnels Extension](https://code.visualstudio.com/docs/remote/tunnels#_remote-tunnels-extension) for VS Code. Install the VS Code extension or your local machine. + +## Contributing + +- Use the `devcontainer.json` to open the repo in a dev container using VS Code. + - There is some test data in the `tests` directory that will be automatically mounted for use since the working directory is the workspace. + - Rebuild the container when you make changes using `Dev Container: Rebuild Container`. + +- Please make a new branch, starting with your name, with any changes, and request a reviewer before merging with the main branch since this image will be used by others. +- Please document using the same conventions (docstrings for each function and class, typing-hints, informative comments). +- Tests are written in the pytest framework. Data used in the tests are defined as fixtures in `tests/fixtures/data.py` (https://docs.pytest.org/en/6.2.x/reference.html#fixtures-api). + +## Build +To build and push via automated CI, just push changes to a branch. +- Pushes to `main` result in an image with the tag `latest`. +- Pushes to other branches have tags with `-test` appended. +- See `.github/workflows` for testing and production workflows. + +To test `test` images locally use after pushing the `test` images via CI: + +``` +docker pull eberrigan/sleap-vscode-tunnel:linux-amd64-test +``` + +then + +``` +docker run -v ./tests/data:/tests/data --gpus all -it eberrigan/sleap-vscode-tunnel:linux-amd64-test bash +``` + +To build locally for testing you can use the command: + +``` +docker build --platform linux/amd64 . +``` + +## Support +contact Elizabeth at eberrigan@salk.edu \ No newline at end of file