Running Microsoft VS Code Remotely – In a Browser Using XPRA and Via a Remote Desktop Application Using RDP

If you’re a new student with a bright new Chromebook or other netbook style computer, what do you do other than panic, or cry, when you’re expected to download and install a desktop application — even a cross-platform one — when you start your course?

A month or so ago I posted some notes on Viewing Dockerised Desktops via an X11 Bridge, novnc and RDP, Sort of… where I found a recipe for running a graphical application running in one container via a browser using a “bridge” application in another container.

(The bridge application container exposed a graphical desktop using http via a browser. The bridge connected to the application container via an X11 connection and then exposed the graphical UI using X11.)

As a building block, this is useful in a couple of ways:

  • the application can be remotely hosted and used to expose a graphical application via a browser (so no installation required);
  • the same recipe can be used to set up a “hub” on a local machine to let you run arbitrary graphical applications on your own computer and access them via a browser.

It can be a bit fiddly though and requires plumbing the application container to the bridge, although Docker Compose can handle that for you.

But it’s still one more thing to go wrong.

And it doesn’t help the student with a Chromebook and no local installation route (let’s set aside the ability to run containers on a Chromebook – the same is probably not true of other netbooks, plus it requires a good spec Chromebook).

One of the problems I’ve found with the browser based approach is that you don’t necessarily get sound… So for our student hoping to rely on accessing an application via a remote server, that could be an issue too…

So here are a couple more recipes for creating simple containerised applications that can be used to provide access to remote desktops, whether they’re remote over the internet, or running “remotely” in a container on your own machine.

To demonstrate, I’ll use the Microsoft VSCode application. This electron app will run cross platform, but that doesn’t directly help if you need to access it remotely…

Method the First: An XPRA Container

Via lanrat/docker-xpra-html5, a base container that includes an XPRA server.

That repo has been archived, perhaps because among other things it was using an old version of Linux. I’ve done an update here — https://github.com/ouseful-backup/docker-xpra-html5 — with a Docker image here — ousefuldemos/docker-xpra-html5 — but still need to check it continues to work as the old one did.

Via the CoCalc Docker container recipe, I cribbed this Dockerfile installation command for VSCode that needs to be added in to the Dockerfile:

#From cocalc-docker
# Microsoft's VS Code
RUN apt-get update && apt-get install -y curl && apt-get clean && \
     curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
  && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
  && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https \
  && apt-get update \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y code

We can use a simple Dockerfile bootstrapped with FROM lanrat/docker-xpra-html5) and then add in the VSCode layer, or we can add it to a cloned copy of the original repository Dockerfile and build our own container from scratch.

I also made a couple of other tweaks to the Dockerfile so that it could use my own command file. But first, we need to create another file (vscode.sh) for our own start command that will launch VSCode, rather than the infinityTerminal, on start:

#! /usr/bin/env bash

#Start the VSCode app
code

#Keep the container running...
tail -f /dev/null

Then copy the file into the container, and set the permissions, via these Dockerfile instructions:

ADD vscode.sh /usr/local/bin/vscode
RUN chmod +x /usr/local/bin/vscode

I also made a change to the CMD, replacing --start-child=infinityTerm with the --start-child=vscode value and using the new CMD line in my Dockerfile:

CMD xpra start --bind-tcp=0.0.0.0:10000 --html=on --start-child=vscode --exit-with-children --daemon=no --xvfb="/usr/bin/Xvfb +extension Composite -screen 0 1920x1080x24+32 -nolisten tcp -noreset" --pulseaudio=no --notifications=no --bell=no

If you’re creating your own Dockerfile bootstrapped from the original Docker image, rather than built from the raw Dockerfile, you’ll need to add the revised CMD command in too. (The CMD statement also looks to have a wide range of other settings that could be useful and that may provide a better experience.)

Building a local copy of the container with docker build -t psychemedia/xpra-vscode . (yes, the . is part of that: it tells the builder to look in the local (.) directory for the Dockerfile) and running it with docker run --rm -d -p 8822:10000 psychemedia/xpra-vscode, the fan on my laptop goes in to overdrive but I can now work in VSCode via my browser:

So that seems to work…

(I also pushed the image to Dockerhub, so you should be able to run the docker run command directly yourself… Alternatively, you can run the command in a new Digital Ocean Docker droplet (see steps 1-5 of the recipe here).)

Method the Second: An RDP Container

In this second example, let’s add the VSCode editor to an image published at danielguerra69/ubuntu-xrdp. Bootstrapping from that container, all we need to do is pull in a VSCode layer:

FROM danielguerra/ubuntu-xrdp

RUN apt-get update && apt-get install -y curl && apt-get clean

RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
  && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
  && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https \
  && apt-get update \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y code

Building this with docker build -t psychemedia/rdp-vscode . and then running it with docker run --rm -d --name uxrdp --hostname terminalserver --shm-size 1g -p 3399:3389 psychemedia/rdp-vscode I can now connect to it on localhost:3399 using a Microsoft Remote Desktop app (available for Windows, Android, iOS and macOS) and login with default credentials (user: ubuntu, password: ubuntu) and access it via a remote desktop window.

(One issue is that resizing the RDP app window doesn’t resize the desktop to fit; there’s perhaps a setting I’m missing somewhere that might help with that…?)

(As before, I also pushed the image to Dockerhub, so you should be able to run the docker run command directly yourself…)

Looking at the Dockerfile, it also looks as if something is exposed on port 9001. If we add -p 9001:9001 (remember, the pattern is -p HOST_PORT:PORT_INSIDE_CONTAINER into the docker start command, and then go to the mapped port, we see a supervisor control panel:

Supervisor_Status

Something like that could be a handy thing to add in to the TM351 VM… Here’s the corresponding supervisor.d config file… (Looks like we can use it as a basis for further monitoring, eg of memory usage. See here.)

I can also confirm that audio (as well as video) works…

Sort of…

Launching a 2GB Digital Ocean Docker droplet with the following user data / startup command:

When I connected to the public IP address for the droplet with port 3389, the RDP worked fine but when I tried to play a Youtube video in Firefox, the buffering garbled the audio really badly. (Maybe a larger droplet instance would have been better…)

Summary

These two simple recipes provide a way for sharing simple GUI apps either via a browser (without audio) or via RDP, with sound available if required. Microsoft provide cross-platform clients for Windows, Mac, Android and IoS.

If the Android client in the Google Play store works for Chromebooks, then a student with a Chromebook should be able to fully access a remotely hosted application over RDP, including support for audio and video.

There is a huge gulf, of course, between being able to get things working, sort of, and getting them working at scale in an educational environment.

The experience may be a bit ropey at times, but if we have one or two students with real issues getting software working, I don’t see why we can’t try to pull together a homebrew solution to provide them with a remotely hosted software environment, albeit perhaps a temporary one.

And each time we try, we’ll maybe figure out a way to smooth it out and improve the experience a bit more.

Or we could teach folk how to launch their own remote server instances  which could be kept running with some sort of file persistence over the life of a course, whether by leaving the server switched on or mounting user files to a storage volume somewhere . (We’d probably have to improve the security layer a bit, at least by showing students how to create their own user credentials. But that’s a problem we’d only have to figure out a recipe for once.)

What keeps winding me up is how folk are so resistant to using computers to do computery things…

PS here’s something else I learned today, ish via @mickaelistria on the Twitterz. The original tweet pointed to a repo that provides access to an Eclipse IDE via a browser: https://github.com/ws-skeleton/eclipse-broadway/ From which I then learned that the GDK Broadway backend provides support for displaying GTK+ applications in a web browser, using HTML5 and web sockets. So that’s another route?

Also via Twitter, @olberger pointed me to https://janitor.technology/ https://github.com/JanitorTechnology/janitor, which looks like it provides an online development environment built around https://github.com/theia-ide/theia .

I’m thoroughly out of my depth with this development environment stuff…

All I’m trying to do is identify the small pieces that can be used to make applications available to students.

For two reasons…

Firstly, so I can experiment with the pieces and get a feel for how they work / what their limitations are / what sorts of richer environments might come to be built on their foundations.

Secondly, so when folk pitch whizzy start-up solutions to us at “only” $X per student seat, I have some mental filters in place so that I can filter out the shiny glare and get a feeling for what’s actually being offered, and maybe what technology it’s built on (or at least, seed me questions so I can try to figure out what it’s built on). And from that, what the limitations and benefits might be. We generally don’t get to hear, make time for, or understand detailed technical sales pitches, but at the end of the day, the tech is a large part of what you’re buying, wrapped up in user experience chrome.

PS here’s an online service that looks like it’s over a ‘native’ web hosted version of VS Code:  StackBlitz; and here’s another, coder.com , with a repo: codercom/code-server.

PPS By the by, VS Code looks like it’s built using this browser based text editor from Microsoft: Monaco.

PPPS @betatim show’s how it’s done… the codercom/code-server running in a Binder container proxied in a Jupyer notebook environment using jupyter-server-proxy: https://github.com/betatim/vscode-binder.

Author: Tony Hirst

I'm a Senior Lecturer at The Open University, with an interest in #opendata policy and practice, as well as general web tinkering...

2 thoughts on “Running Microsoft VS Code Remotely – In a Browser Using XPRA and Via a Remote Desktop Application Using RDP”

  1. Tony, it would be interesting to add some tags to that post so that the 2 posts are interlinked and can be retrieved looking for the same tags (more or less)

Comments are closed.