Skip to Content
Technical Articles

VSCode Development for SAP Cloud Application Programming Model Using Remote – WSL

Introduction

A few weeks ago I started experimenting with WSL2 – Windows Subsystem for Linux. My original work was focused on getting SAP HANA, express edition installed within WSL2. I detailed that successful outcome in this blog post: https://blogs.sap.com/2020/09/30/installing-sap-hana-express-edition-into-wsl2-windows-subsystem-for-linux/

In this blog post and video, I continue exploring WSL2 but today I want to see if I can setup WLS2 for remote container development in VSCode. I want to setup a Linux container within my Windows development machine where I can install all the necessary dependencies for doing SAP Cloud Application Programming Model development and test/debug in a pure Linux environment.

This is similar to the process described in this blog post: Create a development container for CDS in Visual Studio Code.  The difference here is that I will use Windows Subsystem for Linux instead of Docker as the remote container technology. The other obvious difference is that since I’m focused on WSL2, my approach only works if Windows is your host OS.

Video

Also new in this blog post, I’ve recorded a video of all the content as well. Some people prefer to read about a topic, some like to watch videos, and some like a mixture of both.

 

0:00 Introduction
0:24 WSL2 Background and Benefits
1:48 Typical Environment Needed for CAP Development
5:46 My WLS2 Distributions
7:38 Ubuntu
9:00 Shared Docker
11:48 Export Ubuntu Image
13:57 Image Image as New Container
15:37 Test New Container
17:54 A Few Issues With Default User
19:56 Update CAP Version
22:49 Add Docker to New Container
24:23 Launch VSCode Remote WSL
27:54 Install VSCode Extensions
30:38 Debug Node.js App in WSL2
32:21 Closing

WSL2 Background and Benefits

In my previous blog post, I was mostly focused on getting SAP HANA, express edition running in WSL. However I also discussed a few of the general performance and integration benefits of using WSL2. If you’ve not setup WSL2 at all on your Windows development machine then I would suggest several reading links:

https://docs.microsoft.com/en-us/windows/wsl/compare-versions

https://docs.microsoft.com/en-us/windows/wsl/install-win10

But today I want to take WSL2 in a completely different direction.  I want to see if I can use this technology to run an isolate Linux container on my Windows development machine in order to perform SAP Cloud Application Programming Model development.

Today when I use VSCode to perform SAP Cloud Application Programming Model or SAP Fiori development locally, I have to first install and configure a variety of local tools. For instance I have a Node.js runtime and a variety of node.js modules (not the least of which is @sap/cds-dk) installed in my Windows OS.

Sample%20of%20Local%20Setup

Sample of Local Setup

But this can become complex when you want to update say the Node.js runtime version. Or maybe you want to experiment with a new version of the SAP Cloud Application Programming Model.  With all these dependencies installed in the main OS, its difficult to isolate and keep one change from impacting all of your development. So the idea is to instead isolate a separate development environment as a completely separate Linux OS.

We could use Virtual Machines or Docker to accomplish this.  However WSL2 offers Windows users a great alternative option. WSL2 give us the option to run multiple, lightweight Linux containers which startup quickly and have great integration and interaction with the Host OS. This also gives us the opportunity to test and debug in a Linux environment which is very likely a better match to were you will ultimately deploy your code in production.

Setting up a Development Image

First let’s look at my local WSL2 setup.  I run a wsl –list –verbose command.

Initial%20WSL%20Setup

Initial WSL Setup

To begin with I have four WSL2 containers running. The openSUSE-Leap-15.2 is the home to my SAP HANA, express edition instance. We won’t be doing anything with that instance.  The second instance is a bare bones installation of Ubuntu Linux.  I choose Ubuntu because its a relatively small distribution which is generally considered a good compatibility baseline. This is what I will use my development image base.

You might also notice the two docker-desktop* images as well. We will talk about that more in a minute.

Focusing on the Ubuntu baseline image, you can shell directly into it via the wsl command or as I’m doing you can use Windows Terminal and connect directly.

Ubuntu%20Base%20Image

Ubuntu Base Image

In order to prepare this image for being a development container, I just simply install some of the basic tools like Node.js runtime or the @sap/cds-dk module.  Basically the same things I had previously setup in host OS, but now in this container.

While connected to this container, we can test and see that Docker is also already setup here.  I can perform a docker ps to list the local containers.

docker%20ps%20-%20from%20within%20Linux

docker ps – from within Linux

But this Docker server and the images aren’t installed nor running within this Linux container.  Instead I have just one Docker desktop instance running in the Windows Host OS but using WSL as its execution engine (hence the extra two images we saw earlier).

Docker%20WSL%20Integration

Docker WSL Integration

Docker Desktop then supports a special feature under WSL Integration to will automatically configure running distributions to point to and share the single Docker instance.  This is convenient as I can now develop locally inside one or more WSL containers but share a single copy of any Docker images I might need. This also avoids a lot of redundant copies of Docker images.

Create Custom WSL Image

Now that I have my Ubuntu image with the basic, baseline configuration that I want; I can begin the process of making a copy of the image. Using the export and import WSL commands you can take snapshots of a WSL distribution and then put them back into WSL as a copy. This will allow me to create a disposable copy of Ubuntu on my machine specifically for CAP development.  At any time I can make a new copy or revert back to the clean baseline image.

Issuing the export command and waiting 4-5 minutes, we see that the Ubuntu base image plus all of my configuration and additional installations have been written out to a standard ZIP file in my Windows Host file system. I can even open this file using a ZIP utility.

wsl%20--export

wsl –export

Now we can use the wsl –import command to bring the image right back in. But during the import we can provide a new, custom Distribution name and separate storage location.  This allows us to run multiple copies of the same distribution as separate WSL containers.  We now are running both the basic Ubuntu image and at the same time the copy of Linux Ubuntu that we want to use for isolate SAP Cloud Application Programming Model development.

wsl%20--import

wsl –import

A few things I noticed about the copy of the Ubuntu image.  First the default login is different. Instead of logging me in with the Windows user I created for WSL, it seems to be connecting me by default with the root user.  I have to do a bit more research on why this happened as it gave me some differences compared to what I had setup in my base Ubuntu image; but it wasn’t a show stopper. I guess I just feel a little odd using root directly after years of trying to be good from a security standpoint and only using sudo and not switch users or login as root.

The other error I hit was when I tried to update the @sap/cds-dk module. I hit a permission issue at the file system level there which also seemed to be related to the switch from my windows user to the root user. But doing an uninstall of the @sap/cds-dk module and then a reinstall with npm install -g @sap/cds-dk and then everything worked right and the module was updated to the latest.

Launching VSCode

So I’m ready to start doing development targeting this remote container.  This is where the VSCode integration with WSL and the special extension for remote – WSL (https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl) make things so simple. In fact I can just shell into the new Ubuntu-CAP image and run the code command.  This will install or update a VSCode Server within the WSL Linux container.

Launch%20VSCode

Launch VSCode

This launches VSCode but not actually running in Linux.  VScode itself is still running in my Windows Host OS, but it seamlessly connects remotely to the Linux container.  Our project explorer, terminal, and other capabilities are all now pointing into the running Linux environment not the local, Windows one.

VSCode%20Remote%20WSL

VSCode Remote WSL

We could also have used the Remote Explorer within VSCode to browse remote targets (of WSL, SSH, and Docker containers) and connect directly from here as well.

Remote%20Explorer

Remote Explorer

One of my favorite features of working in WSL Remote in VSCode is that each remote container can and does have its own set of extensions.  When I switch to the Extensions view in VSCode I can see the Local – Installed  extensions. These are the ones installed directly in my Windows Host OS and not automatically available and running when running in this Remote WSL mode.  I can choose which extensions I then want to install into this specific WSL remote container.  For instance I might only install a smaller subset of extensions that I want for CAP development and not everything else I have in my main VSCode installation.

VSCode%20Extensions

VSCode Extensions

A big part of the reason to setup and use the Remote WSL based development wasn’t just for the isolation but also the ability to test and debug in a real Linux environment.  I want to test this out so I create a small Node.js application which will return OS level information.

let os = require("os")
let output = {}

output.tmpdir = os.tmpdir()
output.endianness = os.endianness()
output.hostname = os.hostname()
output.type = os.type()
output.platform = os.platform()
output.arch = os.arch()
output.release = os.release()

console.table(output)

I set a breakpoint and run the code from VSCode.  With no special steps or configuration from me, it automatically runs in my Ubuntu Linux container.  And we can see clearly from the OS level being returned that we are in a Linux environment.

Remote%20Execution%20and%20Debugging

Remote Execution and Debugging

Closing

Other than the issues I hit with the switch to root user and associated permissions issues in the clone of my Linux distribution; I’d say this experiment in isolate development using Remote WSL was a big success.

I like the idea of being able to quickly and easily create customized but also isolated development environments.  I also appreciate the opportunity to create a bespoke set of VSCode Extensions for a specific development scenario as well. And finally the testing and debugging within Linux provides better compatibility to my eventual deployment target. Although I’ve only been working in this new setup for a few days now, I’m excited by the possibilities and can imagine I’ll continue with this approach (with maybe a few more specific images for different development scenarios).

3 Comments
You must be Logged on to comment or reply to a post.
  • Hey Thomas Jung

    You can create a wsl.config file in your UbuntuCAP distro in the /etc/

    In there you can add the default user:

    [user]
    default=default_username

    Then you need to restart wsl. But for me then it opens with my user and not with the root-user. Also I have not noticed any permission issues yet after I have done that.

    Kind regards,

    Robin

    • Actually I was just reading about that option the other day. Sounds like a common issue and this is the common solution when copying WSL2 images. Thanks for the suggestion.

      • Indeed, other option seems to be modifying the registries, but I’m not a fan of that option.

        Thanks for the excellent work you are doing together with all the dev advocates!