I imagine your first thought is: why? Well, at Wehkamp we do a lot of cross platform development, but sometimes we end up with shell scripts that do stuff with Docker and Python.

Usually that’s not a problem for Mac, but for Windows it’s a different thing. I have a MacBook Pro, but I’m a .NET developer, that’s why I prefer Windows, so I run Bootcamp.

This article will show how to do Python development in the Windows Subsystem for Linux (WSL) using Visual Studio Code and Docker.

1. Enable virtualization

Intel Virtualization Technology (VT-X) is used by Docker, but when you (cold) boot to Windows, it is disabled. This can be resolved by using the rEFInd boot loader that turns the feature on. More detailed installation instructions can be found here, but this is what I did:

⚠️ I only used this on a MacBook Pro, so use at your own risk. ⚠️

  1. Boot to Mac OS.
  2. Download the rEFInd zip from SourceForge: https://sourceforge.net/projects/refind/files/0.11.4/refind-bin-0.11.4.zip/download and unzip the file.
  3. Open the refind/refind.conf-sample file and change the following lines:
    • On line 13: timeout 5, this will decrease the time you’re waiting for the options screen.
    • On line 485: enable_and_lock_vmx true, this will enable the virtualization. Also: don’t forget to remove the comment # on the beginning of the line.
    • Save the file.
  4. Shutdown your Mac. Power back on and keep pressing Command+R to get into recovery mode.
  5. Go to Utilities in the top menu and click Terminal. Disable System Integrity Protection, so we can load rEFInd, so enter: csrutil disable and reboot by entering reboot.
  6. Open a new terminal window, navigate to the unzipped folder and execute ./refind-install.
  7. Shutdown your Mac. Power back on and keep pressing Command+R to get into recovery mode.
  8. Go to Utilities in the top menu and click Terminal. Enable System Integrity Protection by entering: csrutil enable and reboot by entering reboot.

Now we must boot into Windows and enable Microsoft Hyper V. Open up an elevated PowerShell console (Win+x, a) and enter:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

2. Install Docker

You can install Docker Desktop to run Docker on Windows.

  1. Download the Docker Desktop Installer for Windows here: https://hub.docker.com/?overlay=onboarding.
  2. Install Docker Desktop.
  3. Start Docker Desktop.
  4. When it is started, right click on the tray icon and select Settings.
  5. In the General settings, click Expose daemon on tcp://localhost:2375 without TLS
  6. Close the dialog.

You can check if everything works by running the following PowerShell script:

docker pull hello-world
docker run hello-world

3. Install Ubutu

First, we need to enable the Windows Subsystem for Linux (WSL). Open up an elevated PowerShell console and enter:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

Next, we can install Ubuntu. Just go to https://www.microsoft.com/en-us/p/ubuntu/9nblggh4msv6 and install the the latest version of Ubuntu from the Microsoft Store. After installation is completed, you can specify a username and password. Let’s update the packages to the latest version:

sudo apt-get update -y
sudo apt-get upgrade -y

I like to start Bash by typing it into the run menu. If you’ve played around with WSL before, you might get the error “The system cannot find the path specified”. You can fix this by executing the following line in PowerShell:

 wslconfig /s Ubuntu

4. Install Python using pyenv

There are many ways to install Python on Ubuntu.I use pyenv to install and switch python environments. To install this tool, we first need to install some tools for building Python:

sudo apt-get install --no-install-recommends -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

Now we can install pyenv:

# clone from GitHub
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
# add pyenv to your path
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
# add pyenv to your shell for auto completion
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
# restart your shell so path can be used
exec "$SHELL"

Now we can install python 3.8 (might take some time):

pyenv install 3.8.1
pyenv global 3.8.1
python --version
pip --version

Both python and pip should echo their new versions.

5. Connect Docker in WSL

Now we need to install Docker to Ubuntu, so open it up (Win+R, type bash) and enter:

# dependencies
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# add Docker PGP key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
# add Docker repository
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# install docker community edition and docker compose
sudo apt-get update -y
sudo apt-get install -y docker-ce
# allow current user to access Docker without root
sudo usermod -aG docker $USER

Now we need to connect the WSL Docker to the Windows Docker Desktop service and test it:

echo "export DOCKER_HOST=tcp://localhost:2375" >> ~/.bashrc
source ~/.bashrc
exec "$SHELL"
docker pull hello-world
docker run hello-world

6. Connect Windows Git and WSL git

I use Windows as my default development OS, so I have set up git at Windows. I want to keep using that Windows Git – even when I’m in bash. Let’s add an alias for this to bash:

echo alias git="/mnt/c/Program\ Files/Git/bin/git.exe" >> ~/.bashrc
source ~/.bashrc
exec "$SHELL"

7. Install Visual Studio Code

To run and use Visual Studio Code, do this:

  1. Download and install it in Windows from here: https://code.visualstudio.com/Download
  2. Open up Ubuntu (Win+R and type bash)
  3. Enter: code. This will install VS Code Server for x64, giving you a bridge from WSL to your Visual Studio Code.

Final thoughts

So that’s it; the setup is a little weird – but it really works. I would love it if Apple fixes the virtualization flag, but they did a great job with Bootcamp – so I can’t be too angry with them.

Further reading

Here’s a list of sources and further reading.

Improvements
2019-12-26: Added alias for Windows Git so it can be used from WSL.