I used to mess up my development environment over time by installing all the different experimentation dependencies. This is why I decided to switch to Docker containers.

The Jetson Nano default image comes with Docker runtime pre-installed. To package your app and avoid polluting your device OS with various dependencies, you can use Docker containers as development environments.

In fact, using a container as a development environment is a very similar to using directly a Jetson device for remote development. Here's my post on how to do the latter.


Remote Debugging inside a Container running on a Jetson Device

The NVIDIA Container Runtime on Jetson repo has great information on how to use GPU accelerated containers in both the Jetson family, and an X64 workstation.

Once you choose what's your base container, you'll need to setup a few more things.

You can either clone this repo that contains all the below code, or start from scratch. The assumed file structure of all the following code is:

/keys: Here's where I keep my public ssh key.
/.vscode: Here's where I keep my debugging configuration.
/docker: Inside the docker folder I put the container definitions.
/src: Here's the application source code.

/keys

You will need to setup a passwordless ssh between your host's VSCode and the container. To do this, you'll need to copy your ssh public key in the container's authorized_keys file. To get your public ssh key, run:cat ~/.ssh/id_rsa.pub. Copy the key value in the id_rsa.pub key file that's inside the /keys folder.

My host is a Windows 10 machine and I generally make sure that my Windows and WSL keys are the same. To do this, I've copied my keys from ~/.ssh/ to /mnt/c/users/[YOUR USERNAME]/.ssh/. This way I get a convenience security symmetry.

/.vscode

Here's the my launch.json and how to setup an X Server for forwarding any GUI running on the container to your host (here's more information how to set this up)

{    
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal", 
            "env":
            {
            "DISPLAY": "10.135.62.79:0.0" 
            }
        }
    ]
}
Replace the IP with your host's IP. I'm using the X410 X Server on Windows 10.

/docker

In this example, I've started from a bare minimum, the l4t OS. This dockerfile is self explanatory.

FROM nvcr.io/nvidia/l4t-base:r32.2

ENV DEBIAN_FRONTEND=noninteractive

# Install Python3, Git and OpenCV
RUN apt-get update && apt-get --yes install openssh-server python3-dev python3-pip python3-opencv git
RUN pip3 install --upgrade pip

RUN pip3 install click

ENV LC_ALL C.UTF-8
ENV LANG C.UTF-8

# Set the WORKDIR
WORKDIR /src

ENTRYPOINT service ssh restart && bash

# Install the ssh public key - Remove this in a production deployment
COPY ./keys/id_rsa.pub /tmp/tmp.pub
RUN mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat /tmp/tmp.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && rm -f /tmp/tmp.pub

/src

This is where I put all the application code. You can test that the X forwarding works by opening running the xtest.py. You'll have to install the eog application in the container first by running apt-get install eog in a new VSCode terminal.

Here's the xtest.py code:

import subprocess
subprocess.run(["eog"])

Wiring everything up

On your Jetson device, run:

# Clone the example repo
git clone https://github.com/paloukari/jetson-detectors
cd jetson-remote-development

# Build the dev container
sudo docker build . -f ./docker/Dockerfile.cpu -t object-detection-cpu

# Run the container
sudo docker run --rm --runtime nvidia --privileged -ti -e DISPLAY=$DISPLAY -v "$PWD":/src -p 32001:22 object-detection-cpu

In your host's VSCode, add this information in the Remote-SSH configuration file:

Host Nano
    User spyros
    HostName spyros-nano2
    IdentityFile ~/.ssh/id_rsa

Host NanoContainer
    User root
    HostName spyros-nano2
    IdentityFile ~/.ssh/id_rsa
    Port 32001

Now, you should be able to connect to the NanoContainer Remote SSH host. Last step is to install the Python VSCode extension on the remote host.

The VSCode extensions need to be installed in both machines in a Remote-SSH session

Open the xtest.py and fit F5.

You need to install the eog app in the container.

What we achieved: We can now do remote development from a Windows host to a container running on a Jetson Nano, using VSCode.