Navigate back to the homepage

How to run VS Code as a Container for Remote Development

Sar Malik
December 15th, 2020 · 3 min read

Launch your own Code Server container with preloaded dev tools (SDKs, npm packages, CLIs etc) for an efficient and securely accessible Web IDE in your homelab or private cloud!

Why VS Code in a Container?

Remote development has taken the world by storm, it’s not just a trend but here to stay as a new way that delivers on the promise of work-life balance.

Teams need to adapt rapidly and deploy out infrastructure which enables developer productivity and one of the best ways we’ve found is - speed to onboarding.

Getting up and running is simple as scaling containers with all the tooling and personalized preferences ready to go. Writing code has never been easier, anywhere and on any device powered by your own cloud.

Getting Started

We’ve provided the full code samples used in this guide, checkout our Github repository to get started.

Clone the repo on a host server with docker or podman configured. It’s recommended to attach mount points for storing your codebase isolated from the container runtime for redundancy and failover management.

1$ git clone https://github.com/DigitalTransformation/vs-code-container-with-ssl.git

Next, we’ll setup the required environment variables and data paths using the included .env.template replicated as .env (note: it’s excluded by default in .gitignore).

Persistent storage for extensions and vscode settings can also be enabled by mapping HOST_* variables for convenience against container restarts and rebuilds. Otherwise you’ll be quite unhappy to see all the preferences wiped out!

The popular vs code extension settings-sync is also another great way to backup preferences onto private gists but does require reinstalling extensions on every new image build.

Here’s an example of what you’ll need to define in .env:

1VIRTUAL_HOST=10.0.0.1
2VIRTUAL_PORT=8555
3
4HOST_CONFIG_PATH=./config
5HOST_LOG_PATH=./logs
6
7HOST_CODE_PATH=/mnt/codebase
8CODE_PATH=/code
9
10TZ=America/New_York
11PASSWORD=<PASSWORD>
12SUDO_PASSWORD=<SUDO_PASSWORD>

Nginx is used to reroute traffic from [::]:80 to upstream HTTPS port [::]:8443 with self-signed SSL certificates. Checkout and run the generate_certs.sh script to emit the required certificates with signing key using openssl.

Place both the nginx.conf and certs under the paths defined in code-server.yaml.

1listen [::]:443 ssl default_server;
2 ssl_certificate /etc/nginx/certs/ssl.crt;
3 ssl_certificate_key /etc/nginx/certs/ssl.key;
4 ssl_protocols TLSv1.1 TLSv1.2;
5 ssl_prefer_server_ciphers on;
6 ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DHE+AES128:!ADH:!AECDH:!MD5;

Finally, deploy the container stack on the docker host using the command docker-compose -f code-server.yaml up. It may take 15-20 minutes depending on your hardware and network bandwidth for the initial build. The dockerfile pre-configures a number of devtools and updates the base image packages.

To comply with Docker CIS, resource limits are defined on each of the containers but can be customized to your hardware in the compose code-server.yaml file.

Pre-Installed Dev Tools

Here’s a quick overview of what the dockerfile does to extend the linuxserver/code-server base image. This allows containers to be rapidly deployed and scaled up for usage on dev teams with tooling ready to go.

The output image includes SDKs for cloud native app development workloads such as React, Node, C#, AWS and Azure Cloud CLIs.

1* AWS CLI Tools
2 * aws-shell
3 * amplify cli
4* Azure CLI
5* Netlify CLI
6* NPM packages
7 * yarn (upstream)
8 * gatsby-cli
9 * gulp
10 * create-react-app
11* .NET Core SDK and Runtime
12 * 5.0.0
13 * 3.1.0
14 * 2.1.0
15* Python global env
16 * python3 python3-pip python3-dev
17* Ubuntu apt packages
18 * Networking
19 * wget
20 * apt-transport-https
21 * libssl-dev libffi-dev
22 * Tools
23 * ranger
24 * tree
25 * unzip
26 * ansible
27 * vim
28 * htop
29 * iputils-ping
30 * OS/Misc
31 * systemd
32 * build-essential
33 * ffmpeg
34 * youtube-dl
35 * chromium-browser
36 * Default shell --> zsh/oh-my-zsh
37 * zsh-syntax-highlighting
38 * zsh-autosuggestions
39 * zsh-completions
40 * history-search-multi-word

Refer to the Dockerfile for image layers. Our build image size was well over 6.5GB but can be as minimal as your requirements for dev tools.

Remote Debugging

By default the dockerfile and code-server.yaml are set to expose port ranges 5000-5010 and 8000-8010 commonly used for web app development. Customize this for your workload such as React, Gatsby, Angular, Django, etc. to allow for remote debugging HTTP instances that are running inside the container.

To allow external access on node frameworks that depend http-server (instantiated with npm or yarn) you may need to also update your package.json and bind the runtime to the host ip instead of localhost.

Here are a few common examples:

1{
2 "scripts": {
3 "ng:start": "ng serve --host 0.0.0.0",
4 "npm:start": "http-server --host 0.0.0.0",
5 "gatsby:start": "gatsby develop --host 0.0.0.0"
6 }
7}

Alternatively, if you’d prefer not to expose ports, check out the vscode-browser-preview extension which enables chromium based inspection and debugging within the container itself.

Security Considerations

As the base image extends ubuntu:18.04, additional steps have been taken to add security measures with hosts file, fail2ban and clamav packages preloaded. These are precautionary against attacks but insufficient against (un)known breaches.

Log Analytics

It’s strongly recommended to configure a remote syslog daemon for log analytics with auditd enabled, here’s our guide on using solutions such as Graylog2.

Ports

There’s a wide range of tcp ports exposed and mapped directly to the host for remote debugging apps running inside the container. By default, only the code-server is allocated on ports 8443 and localhost:8080.

1$ netstat -tnlp
2
3Active Internet connections (only servers)
4Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
5tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN 299/node
6tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN -

For dev workloads outside of a homelab or private cloud behind firewalls, using an nginx reverse proxy with HTTPS and auth redirects is vital to preventing sensitive code exposure.

What’s next?

Deploying VS Code Server in a container is a great way to provide for flexible development infrastructure in your home lab or for your team.

Paired with VPN access and all your custom settings, Web IDEs make for the future of remote coding. It’s rapidly scalable, gets you to coding a lot quicker, and on any device.

Be sure to checkout the Github repository where we’ve provided the full code samples that can be used to deploy your own code-server in minutes.

Got a cool idea or tip for developers? Drop us a message to be featured on our social channels.

More articles from Quant ONE Inc.

Ensuring Success Key considerations for an Agile Sales Organization

Our research suggests that as companies shift to an agile sales operating model, they’ll encounter a number of key challenges.

November 16th, 2020 · 3 min read

Executive Guide to Digital Strategy

Explore the critical steps companies can take to become digital leaders and beat the competition despite having a late start.

November 5th, 2020 · 4 min read

Build Cloud Native
Build with Certainty

© Quant ONE Inc. All Rights Reserved