Run Docker In Linux Subsystem For Windows



As a Windows Insider, I tried the Windows Subsystem for Linux since day 1 and I really enjoyed it. Now that Falls Creators U p date is out, I'm using the Ubuntu distro from the store, and the. This step-by-step guide will help you get started developing with remote containers by setting up Docker Desktop for Windows with WSL 2 (Windows Subsystem for Linux, version 2). Docker Desktop for Windows is available for free and provides a development environment for building, shipping, and running dockerized apps. Last June, the Docker team announced that they will be investing in getting Docker running with the Windows Subsystem for Linux (WSL). All of this is made possible with the recent changes to the architecture of WSL to run within a lightweight virtual machine (VM), which we talked about in an earlier blog post about WSL 2.

-->

This step-by-step guide will help you get started developing with remote containers by setting up Docker Desktop for Windows with WSL 2 (Windows Subsystem for Linux, version 2).

Docker Desktop for Windows is available for free and provides a development environment for building, shipping, and running dockerized apps. By enabling the WSL 2 based engine, you can run both Linux and Windows containers in Docker Desktop on the same machine.

Overview of Docker containers

Run docker in linux subsystem for windows 10

Docker is a tool used to create, deploy, and run applications using containers. Containers enable developers to package an app with all of the parts it needs (libraries, frameworks, dependencies, etc) and ship it all out as one package. Using a container ensures that the app will run the same regardless of any customized settings or previously installed libraries on the computer running it that could differ from the machine that was used to write and test the app's code. This permits developers to focus on writing code without worrying about the system that code will be run on.

Docker containers are similar to virtual machines, but don't create an entire virtual operating system. Instead, Docker enables the app to use the same Linux kernel as the system that it's running on. This allows the app package to only require parts not already on the host computer, reducing the package size and improving performance.

Continuous availability, using Docker containers with tools like Kubernetes, is another reason for the popularity of containers. This enables multiple versions of your app container to be created at different times. Rather than needing to take down an entire system for updates or maintenance, each container (and it's specific microservices) can be replaced on the fly. You can prepare a new container with all of your updates, set up the container for production, and just point to the new container once it's ready. You can also archive different versions of your app using containers and keep them running as a safety fallback if needed.

Run Docker In Linux Subsystem For Windows 10

To learn more, checkout the Introduction to Docker containers on Microsoft Learn.

Prerequisites

  • Ensure your machine is running Windows 10, updated to version 2004, Build 18362 or higher.
  • Enable WSL, install a Linux distribution, and update to WSL 2.
  • Download and install the Linux kernel update package.
  • Install Visual Studio Code(optional). This will provide the best experience, including the ability to code and debug inside a remote Docker container and connected to your Linux distribution.
  • Install Windows Terminal(optional). This will provide the best experience, including the ability to customize and open multiple terminals in the same interface (including Ubuntu, Debian, PowerShell, Azure CLI, or whatever you prefer to use).
  • Sign up for a Docker ID at Docker Hub(optional).

Note

WSL can run distributions in both WSL version 1 or WSL 2 mode. You can check this by opening PowerShell and entering: wsl -l -v. Ensure that the your distribution is set to use WSL 2 by entering: wsl --set-version <distro> 2. Replace <distro> with the distro name (e.g. Ubuntu 18.04).

In WSL version 1, due to fundamental differences between Windows and Linux, the Docker Engine couldn't run directly inside WSL, so the Docker team developed an alternative solution using Hyper-V VMs and LinuxKit. However, since WSL 2 now runs on a Linux kernel with full system call capacity, Docker can fully run in WSL 2. This means that Linux containers can run natively without emulation, resulting in better performance and interoperability between your Windows and Linux tools.

Install Docker Desktop

With the WSL 2 backend supported in Docker Desktop for Windows, you can work in a Linux-based development environment and build Linux-based containers, while using Visual Studio Code for code editing and debugging, and running your container in the Microsoft Edge browser on Windows.

To install Docker (after already installing WSL 2):

  1. Download Docker Desktop and follow the installation instructions.

  2. Once installed, start Docker Desktop from the Windows Start menu, then select the Docker icon from the hidden icons menu of your taskbar. Right-click the icon to display the Docker commands menu and select 'Settings'.

  3. Ensure that 'Use the WSL 2 based engine' is checked in Settings > General.

  4. Select from your installed WSL 2 distributions which you want to enable Docker integration on by going to: Settings > Resources > WSL Integration.

  5. To confirm that Docker has been installed, open a WSL distribution (e.g. Ubuntu) and display the version and build number by entering: docker --version

  6. Test that your installation works correctly by running a simple built-in Docker image using: docker run hello-world

Tip

Here are a few helpful Docker commands to know:

  • List the commands available in the Docker CLI by entering: docker
  • List information for a specific command with: docker <COMMAND> --help
  • List the docker images on your machine (which is just the hello-world image at this point), with: docker image ls --all
  • List the containers on your machine, with: docker container ls --all or docker ps -a (without the -a show all flag, only running containers will be displayed)
  • List system-wide information regarding the Docker installation, including statistics and resources (CPU & memory) available to you in the WSL 2 context, with: docker info

Develop in remote containers using VS Code

To get started developing apps using Docker with WSL 2, we recommend using VS Code, along with the Remote-WSL extension and Docker extension.

Run Docker In Linux Subsystem For Windows
  • Install the VS Code Remote-WSL extension. This extension enables you to open your Linux project running on WSL in VS Code (no need to worry about pathing issues, binary compatibility, or other cross-OS challenges).

  • Install the VS code Remote-Containers extension. This extension enables you to open your project folder or repo inside of a container, taking advantage of Visual Studio Code's full feature set to do your development work within the container.

  • Install the VS Code Docker extension. This extension adds the functionality to build, manage, and deploy containerized applications from inside VS Code. (You need the Remote-Container extension to actually use the container as your dev environment.)

Let's use Docker to create a development container for an existing app project.

  1. For this example, I'll use the source code from my Hello World tutorial for Django in the Python development environment set up docs. You can skip this step if you prefer to use your own project source code. To download my HelloWorld-Django web app from GitHub, open a WSL terminal (Ubuntu for example) and enter: git clone https://github.com/mattwojo/helloworld-django.git

    Note

    Always store your code in the same file system that you're using tools in. This will result in faster file access performance. In this example, we are using a Linux distro (Ubuntu) and want to store our project files on the WSL file system wsl. Storing project files on the Windows file system would significantly slow things down when using Linux tools in WSL to access those files.

  2. From your WSL terminal, change directories to the source code folder for this project:

  3. Open the project in VS Code running on the local Remote-WSL extension server by entering:

    Confirm that you are connected to your WSL Linux distro by checking the green remote indicator in the bottom-left corner of your VS Code instance.

  4. From the VS Code command pallette (Ctrl + Shift + P), enter: Remote-Containers: Open Folder in Container... If this command doesn't display as you begin to type it, check to ensure that you've installed the Remote Container extension linked above.

  5. Select the project folder that you wish to containerize. In my case, this is wslUbuntu-20.04homemattwojoreposhelloworld-django

  6. A list of container definitions will appear, since there is no DevContainer configuration in the project folder (repo) yet. The list of container configuration definitions that appears is filtered based on your project type. For my Django project, I'll select Python 3.

  7. A new instance of VS Code will open, begin building our new image, and once the build completed, will start our container. You will see that a new .devcontainer folder has appeared with container configuration information inside a Dockerfile and devcontainer.json file.

  8. To confirm that your project is still connected to both WSL and within a container, open the VS Code integrated terminal (Ctrl + Shift + ~). Check the operating system by entering: uname and the Python version with: python3 --version. You can see that the uname came back as 'Linux', so you are still connected to the WSL 2 engine, and Python version number will be based on the container config that may differ from the Python version installed on your WSL distribution.

  9. To run and debug your app inside of the container using Visual Studio Code, first open the Run menu (Ctrl+Shift+D or select the tab on the far left menu bar). Then select Run and Debug to select a debug configuration and choose the configuration that best suites your project (in my example, this will be 'Django'). This will create a launch.json file in the .vscode folder of your project with instructions on how to run your app.

  10. From inside VS Code, select Run > Start debugging (or just press the F5 key). This will open a terminal inside VS Code and you should see a result saying something like: 'Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.' Hold down the Control key and select the address displayed to open your app in your default web browser and see your project running inside of its container.

You have now successfully configured a remote development container using Docker Desktop, powered by the WSL 2 backend, that you can code in, build, run, deploy, or debug using VS Code!

Troubleshooting

WSL docker context deprecated

If you were using an early Tech Preview of Docker for WSL, you may have a Docker context called 'wsl' that is now deprecated and no longer used. You can check with the command: docker context ls. You can remove this 'wsl' context to avoid errors with the command: docker context rm wsl as you want to use the default context for both Windows and WSL2.

Possible errors you might encounter with this deprecated wsl context include: docker wsl open //./pipe/docker_wsl: The system cannot find the file specified. or error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_wsl/v1.40/images/json?all=1: open //./pipe/docker_wsl: The system cannot find the file specified.

For more on this issue, see How to set up Docker within Windows System for Linux (WSL2) on Windows 10.

Trouble finding docker image storage folder

Docker creates two distro folders to store data:

  • wsl$docker-desktop
  • wsl$docker-desktop-data

You can find these folders by opening your WSL Linux distribution and entering: explorer.exe . to view the folder in Windows File Explorer. Enter: wsl<distro name>mntwsl replacing <distro name> with the name of your distribution (ie. Ubuntu-20.04) to see these folders.

Find more on locating docker storage locations in WSL, see this issue from the WSL repo or this StackOverlow post.

For more help with general troubleshooting issues in WSL, see the Troubleshooting doc.

Additional resources

The Visual Studio Code Remote - WSL extension lets you use the Windows Subsystem for Linux (WSL) as your full-time development environment right from VS Code. You can develop in a Linux-based environment, use Linux-specific toolchains and utilities, and run and debug your Linux-based applications all from the comfort of Windows.

The extension runs commands and other extensions directly in WSL so you can edit files located in WSL or the mounted Windows filesystem (for example /mnt/c) without worrying about pathing issues, binary compatibility, or other cross-OS challenges.

This lets VS Code provide a local-quality development experience — including full IntelliSense (completions), code navigation, and debugging — regardless of where your code is hosted.

Getting started

Note: After reviewing this topic, you can get started with the introductory WSL tutorial.

Installation

To get started, you need to:

  1. Install the Windows Subsystem for Linux along with your preferred Linux distribution.

    Note: WSL 1 does have some known limitations for certain types of development. Also, extensions installed in Alpine Linux may not work due to glibc dependencies in native source code inside the extension. See the Remote Development and Linux article for details.

  2. Install Visual Studio Code on the Windows side (not in WSL).

    Note: When prompted to Select Additional Tasks during installation, be sure to check the Add to PATH option so you can easily open a folder in WSL using the code command.

  3. Install the Remote Development extension pack.

Open a remote folder or workspace

From the WSL terminal

Opening a folder inside the Windows Subsystem for Linux in VS Code is very similar to opening up a Windows folder from the command prompt or PowerShell.

  1. Open a WSL terminal window (using the start menu item or by typing wsl from a command prompt / PowerShell).

  2. Navigate to a folder you'd like to open in VS Code (including, but not limited to, Windows filesystem mounts like /mnt/c)

  3. Type code . in the terminal. When doing this for the first time, you should see VS Code fetching components needed to run in WSL. This should only take a short while, and is only needed once.

    Note: If this command does not work, you may need to restart your terminal or you may not have added VS Code to your path when it was installed.

  4. After a moment, a new VS Code window will appear, and you'll see a notification that VS Code is opening the folder in WSL.

    VS Code will now continue to configure itself in WSL and keep you up to date as it makes progress.

  5. Once finished, you now see a WSL indicator in the bottom left corner, and you'll be able to use VS Code as you would normally!

That's it! Any VS Code operations you perform in this window will be executed in the WSL environment, everything from editing and file operations, to debugging, using terminals, and more.

From VS Code

Alternatively, you can open a Remote WSL window directly from VS Code:

  1. Start VS Code.
  2. Press F1, select Remote-WSL: New Window for the default distro or Remote-WSL: New Window using Distro for a specific distro.
  3. Use the File menu to open your folder.

If you already have a folder open, you can also use the Remote-WSL: Reopen in WSL command. You will be prompted which distro to use.

If you are in a WSL window and want to open the current input in a local window, use Remote-WSL: Reopen in Windows.

From the Windows command prompt

To open a WSL window directly from a Windows prompt use the --remote command line parameter:

code --remote wsl+<distro name> <path in WSL>

for example: code --remote wsl+Ubuntu /home/jim/projects/c

Working with Git

If you are working with the same repository in WSL and Windows, be sure to set up consistent line endings. See tips and tricks for details.

You can also avoid passwords by configuring WSL to use the Windows Git credential manager. See tips and tricks for details.

Managing extensions

VS Code runs extensions in one of two places: locally on the UI / client side, or in WSL. While extensions that affect the VS Code UI, like themes and snippets, are installed locally, most extensions will reside inside WSL.

If you install an extension from the Extensions view, it will automatically be installed in the correct location. Once installed, you can tell where an extension is installed based on the category grouping. There will be Local - Installed category and one for WSL.

Note: If you are an extension author and your extension is not working properly or installs in the wrong place, see Supporting Remote Development for details.

Local extensions that actually need to run remotely will appear dimmed and disabled in the Local - Installed category. Select Install to install an extension on your remote host.

You can also install all locally installed extensions inside WSL by going to the Extensions view and selecting Install Local Extensions in WSL: [Name] using the cloud button at the right of the Local - Installed title bar. This will display a drop down where you can select which locally installed extensions to install in your WSL instance.

Opening a terminal in WSL

Opening a terminal in WSL from VS Code is simple. Once folder is opened in WSL, any terminal window you open in VS Code (Terminal > New Terminal) will automatically run in WSL rather than locally.

You can also use the code command line from this same terminal window to perform a number of operations such as opening a new file or folder in WSL. Type code --help to see what options are available from the command line.

Debugging in WSL

Once you've opened a folder in WSL, you can use VS Code's debugger in the same way you would when running the application locally. For example, if you select a launch configuration in launch.json and start debugging (F5), the application will start on remote host and attach the debugger to it.

See the debugging documentation for details on configuring VS Code's debugging features in .vscode/launch.json.

WSL specific settings

VS Code's local user settings are also reused when you have opened a folder in WSL. While this keeps your user experience consistent, you may want to vary some of these settings between your local machine and WSL. Fortunately, once you have connected to WSL, you can also set WSL specific settings by running the Preferences: Open Remote Settings command from the Command Palette (F1) or by selecting the Remote tab in the Settings editor. These will override any local settings you have in place whenever you open a folder in WSL.

Advanced: Environment setup script

When VS Code Remote is started in WSL, no shell startup scripts are run. This was done to avoid issues with startup scripts that are tuned for shells. If you want to run additional commands or modify the environment this can be done in a setup script ~/.vscode-server/server-env-setup (Insiders: ~/.vscode-server-insiders/server-env-setup). If present, the script is processed before the server is started.

The script needs to be a valid Bourne shell script. Be aware that an invalid script will prevent the server from starting up. If you end up with a script that prevents the server from starting, you will have to use a regular WSL shell and delete or rename the setup script.

Check the WSL log (Remote WSL: Open WSL Log) for output and errors.

Advanced: Opening a WSL 2 folder in a container

If you are using WSL 2 and Docker Desktop's WSL 2 back-end, you can use the Remote - Containers extension to work with source code stored inside WSL! Just follow these steps:

  1. If you have not already, install and setup Docker Desktop's WSL 2 support.

    Tip: Go to Settings > Resources > WSL Integration and enable Docker integration with the WSL distribution you will be using.

  2. If you have not already, install the Remote - Containers extension along with the WSL extension.

  3. Next, open your source code folder in WSL as you would normally.

  4. Once your folder is open in WSL, select Remote-Containers: Reopen Folder in Container from the Command Palette (F1).

  5. If the folder does not have a .devcontainer/devcontainer.json file in it, you'll be asked to pick a starting point from a filterable list or an existing Dockerfile or Docker Compose file (if one exists).

  6. The VS Code window (instance) will reload and start building the dev container. A progress notification provides status updates.

  7. After the build completes, VS Code will automatically connect to the container. You can now work with the your source code from inside the container.

See the Remote - Containers documentation for more information.

Known limitations

This section contains a list of common know issues with WSL. The intent is not to provide a complete list of issues but to highlight some of the common problems seen with WSL.

See here for a list of active issues related to WSL.

I see EACCESS: permission denied error trying to rename a folder in the open workspace in WSL 1

That's a known problem with the WSL file system implementation (Microsoft/WSL#3395, Microsoft/WSL#1956) caused by the file watcher active by VSCode. The issue will only be fixed in WSL 2.

To avoid the issue, set remote.WSL.fileWatcher.polling to true. However, polling based file watching has a performance impact for large workspaces.

For large workspace you want to increase the polling interval: remote.WSL.fileWatcher.pollingInterval and control the folders that are watched: files.watcherExclude.

WSL 2 does not have that file watcher problem is also not affected by the new setting.

Golang in WSL 1

IssueExisting issues
Delve debugger doesn't work under WSLgo-delve/delve#810, Microsoft/vscode-go#926

Node.js in WSL 1

IssueExisting issues
NodeJS Error: spawn EACCES (different variants of this error)Microsoft/WSL#3886
Webpack HMR not workingMicrosoft/WSL#2709
Firebase via node unusably slow only on WSLMicrosoft/WSL#2657

Git limitations

If you clone a Git repository using SSH and your SSH key has a passphrase, VS Code's pull and sync features may hang when running remotely. Either use an SSH key without a passphrase, clone using HTTPS, or run git push from the command line to work around the issue.

Docker Extension limitations

While the Docker extension can run both remotely and locally, if it is already installed locally, you will be unable to install on a remote SSH host without first uninstalling it locally. We will address this problem in a future VS Code release.

Extension limitations

Many extensions will work in WSL without modification. However, in some cases, certain features may require changes. If you run into an extension issue, see here for a summary of common problems and solutions that you can mention to the extension author when reporting the issue.

In addition, some extensions installed in an WSL when using an Alpine Linux-based distribution may not work due to glibc dependencies in native code inside the extension. See the Remote Development with Linux article for details.

Common questions

Why am I asked to change the default distro?

Run Docker In Windows Subsystem For Linux

When using Remote-WSL: New Window using Distro and running on WSL older than Windows 10, May 2019 Update (version 1903) you will be asked to switch the default distribution as the WSL command can only work on the default distro as it does not support the -d option yet.

You can always manually switch the default distro by using wslconfig.exe.

For example:

You can see which distributions you have installed using:

I'm seeing an error about a missing library or dependency

Some extensions rely on libraries not found in the vanilla install of certain WSL Linux distributions. You can add additional libraries into your Linux distribution by using its package manager. For Ubuntu and Debian based distributions, run sudo apt-get install <package> to install the needed libraries. Check the documentation for your extension or the runtime that is mentioned for additional installation details.

What are the connectivity requirements for the Remote - WSL extension?

The Remote - WSL extension and VS Code Server require outbound HTTPS (port 443) connectivity to:

  • update.code.visualstudio.com
  • marketplace.visualstudio.com
  • vscode.blob.core.windows.net
  • *.vo.msecnd.net (Azure CDN)
  • *.gallerycdn.vsassets.io (Azure CDN)

Some extensions (like C#) download secondary dependencies from download.microsoft.com or download.visualstudio.microsoft.com. Others (like Visual Studio Live Share) may have additional connectivity requirements. Consult the extension's documentation for details if you run into trouble.

All other communication between the server and the VS Code client is accomplished through an random local TCP port. You can find a list of locations VS Code itself needs access to in the network connections article.

Subsystem

I'm behind a proxy and have connectivity issues

Proxy settings might be missing on either the Windows or the WSL side.

When a remote window is opened out of VSCode, the Remote - WSL extension tries to download the VSCode server on the Windows side. It therefore uses the Window side proxy configuration:

  • inherited from the OS settings
  • as described in Network Connections in Visual Studio Code

When the remote VSCode is started from a WSL terminal, the download is done using wget in the WSL distro. Proxy settings can be configured in:

  • wget proxy settings: https://stackoverflow.com/questions/11211705/how-to-set-proxy-for-wget
  • manually in the server setup script

Once the server is up and running the proxy settings on the Remote tab are used.

Can I force an extension to run locally / remotely ?

Extensions are typically designed and tested to either run locally or remotely, not both. However, if an extension supports it, you can force it to run in a particular location in your settings.json file.

For example, the setting below will force the Docker extension to run locally and Debugger for Chrome extension to run remotely instead of their defaults:

A value of 'ui' instead of 'workspace' will force the extension to run on the local UI/client side instead. Typically, this should only be used for testing unless otherwise noted in the extension's documentation since it can break extensions. See the article on Supporting Remote Development for details.

As an extension author, what do I need to do?

The VS Code extension API abstracts away local/remote details so most extensions will work without modification. However, given extensions can use any node module or runtime they want, there are situations where adjustments may need to be made. We recommend you test your extension to be sure that no updates are required. See Supporting Remote Development for details.

Questions or feedback

  • See Tips and Tricks or the FAQ.
  • Search on Stack Overflow.
  • Add a feature requests or report a problem.
  • Contribute to our documentation or VS Code itself.
  • See our CONTRIBUTING guide for details.