Lei Mao bio photo

Lei Mao

Machine Learning, Artificial Intelligence, Computer Science.

Twitter Facebook LinkedIn GitHub   G. Scholar E-Mail RSS

Introduction

Sometimes, we would like to develop or debug programs which could only be run on a remote powerful host server, such as a multi-GPU deep learning training program. Setting up a containerized development environment on the host server and being able to communicate to the remote containerized development environment via local IDEs are necessary. It turns out that VS Code could do this with its extensions.


In this blog post, I would like to talk about how to set up the VS Code Docker development environment on a remote host, develop and debug programs in the remote Docker development environment from local VS Code GUI.

Protocol

SSH Key Based Authentication

Follow the instruction to set up the SSH key based authentication to the remote host server, so that we don’t need password every time to login to the remote host server.


Concretely, if we don’t have the public key, which is usually ~/.ssh/id_rsa.pub, generated, we could generate the public key by running the following command on the local computer.

$ ssh-keygen -t rsa -b 4096

Once we have generated the public key, we would have to copy the public key to the remote host by running the following command. We would need to enter the password once to the remote host server.

$ export USER_AT_HOST="your-user-name-on-host@hostname"
$ export PUBKEYPATH="$HOME/.ssh/id_rsa.pub"

$ ssh-copy-id -i "$PUBKEYPATH" "$USER_AT_HOST"

Once the SSH key based authentication was set up, we no longer have have enter the password when we login the remote host server. Verify this by SSH into the remote host.

$ ssh your-user-name-on-host@hostname

VS Code Settings

By default, the VS Code Remote-Container uses local Docker host. This means that we are actually running the containers on the local computer. To use the container running on the remote host server, we have to add "docker.host":"your-user-name-on-host@hostname" to VS Code settings.json. It is usually located in ~/.config/Code/User/.

{
    "cmake.configureOnOpen": true,
    "C_Cpp.updateChannel": "Insiders",
    "window.zoomLevel": 0,
    "editor.minimap.enabled": true,
    "cSpell.userWords": [
        "uncorrelatonship"
    ],
    "docker.host":"your-user-name-on-host@hostname"
}

In addition, it is required to install the Remote Development extension in VS Code.

VS Code Workspace on Host

We would have to create a directory on the remote host as the workspace for VS Code. We could transfer existing files from local to remote host or transfer new or modified files from remote host to local.


On remote host, we run the following command to create a directory.

$ mkdir -p /home/leimao/Workspace/vs-remote-workspace

On the local computer, we transfer the file to remote host using scp. We could also use rsync or whatever transfer tools we feel comfortable with.

$ scp hello.bash your-user-name-on-host@hostname:/home/leimao/Workspace/vs-remote-workspace

On the remote host, we could verify the file has been successfully transferred.

$ cat /home/leimao/Workspace/vs-remote-workspace/hello.bash
echo "Hello Underworld!"

VS Code Workspace on Local Computer

Create a directory for VS Code Workspace. Create a devcontainer.json in the subdirectory .devcontainer. Use the JSON similar to the following one.

// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.117.1/containers/docker-existing-dockerfile
{
	"name": "VS Code Remote Demo",

	// Sets the run context to one level up instead of the .devcontainer folder.
	"context": "..",

	// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
	"dockerFile": "../docker/nvidia.Dockerfile",

	// Set *default* container specific settings.json values on container create.
	"settings": { 
		"terminal.integrated.shell.linux": null
	},

	// Add the IDs of extensions you want installed when the container is created.
	"extensions": [],

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Uncomment the next line to run commands after the container is created - for example installing git.
	// "postCreateCommand": "apt-get update && apt-get install -y git",

	// Uncomment when using a ptrace-based debugger like C++, Go, and Rust
	// "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
    "runArgs": [ "--gpus", "device=0" ],

	// Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-in-docker.
	// "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ],

	// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
	// "remoteUser": "vscode"

    // Using volume
	// "image": "ubuntu-remote-test:0.0.1", // Or "dockerFile"
	// "workspaceFolder": "/workspace",
	// "workspaceMount": "source=remote-workspace,target=/workspace,type=volume"

	// Using bind
	// /home/leimao/Workspace/vs-remote-workspace/ is a directory on the remote host computer
    // "workspaceFolder" is the folder in the Docker container as workspace
    // target=/workspace is the folder in the Docker container that the workspace on the host server are going to bind to
	"workspaceFolder": "/workspace",
	"workspaceMount": "source=/home/leimao/Workspace/vs-remote-workspace/,target=/workspace,type=bind,consistency=cached",
}

Note that "dockerFile" has to correctly point to the local Dockerfile we are going to use. We also provide additional Docker running arguments to "runArgs".

Start VS Code Remote-Container

Click Remote-Containers: Open Folder in Container. Open the local workspace that has the .devcontainer/devcontainer.json we have just configured.

The first time we run this might take a while since the remote host server has to build the Docker image and start Docker container. Once it has been successfully started, we would see the following layout in VS Code. The hello.sh file we have just transferred to the remote host workspace is also shown in VS Code workspace.

Verify the container is running successfully as expected. We could see that the NVIDIA docker container instance has successfully run by using nvidia-smi and the GPU is GeForce GT 640, a very old one, which matches to the one I installed on my remote host server.

We can then run programs in the VS Code terminal or debug programs in the VS interface.

Installing VS Code extensions on the remote host server might also be helpful for development.

After installation, the VS Code extensions on the remote host server would be shown in an independent panel.

Collect Files

Once the development has finished, don’t forget to transfer the files back from the remote host to the local computer.

Caveats

VS Code also has a Remote - SSH extension. The user would be able to use to SSH into a remote host server and modify the files on the remote host server on local VS Code GUI. However, the programs might not be able to run on the host server native system, and VS Code and its useful debugging extensions could not be directly used in the Docker container on the host server.

References