SPFx Development with Docker & VS Code

Developing SharePoint Framework (SPFx) solutions requires a compatible version of Node.js, the SPFx generator and its associated build tools. Keeping these tools working together can become awkward when you work across multiple projects or need to switch between toolchain versions.

One way to simplify SPFx development is to use Docker and Visual Studio Code Dev Containers. Rather than installing Node.js and the SPFx toolchain directly on Windows, you run them inside a Linux container managed by Docker Desktop.

Although this guide targets Windows developers, the container uses Linux, with WSL 2 providing the underlying environment. VS Code connects directly to the container, allowing you to edit code, run commands and build solutions from your familiar development environment. In this article, we’ll set up a repeatable SPFx development environment using Docker Desktop, WSL 2 and VS Code.

Why use Docker for SPFx development?

A container provides a consistent environment for your development tools. Instead of installing Node.js, Yeoman and the SPFx generator directly on Windows, you install them inside a container that can be recreated when needed.

There are several advantages to this approach:

  • Keep your Windows installation clean. The Node.js and SPFx development toolchain lives inside the container.
  • Reproduce the environment. The configuration files describe the tools and versions used by the project.
  • Avoid version conflicts. Different projects can use separate development containers.
  • Work in VS Code. Edit files, use the integrated terminal and run build commands as usual.
  • Share the setup. Commit the container configuration to source control so other developers can use the same environment.

The container runs Linux, but that doesn’t mean you need to develop on a Linux desktop. Windows remains your host operating system, and VS Code connects to the container.

Prerequisites

You’ll need the following:

  • Windows 11, or a compatible Windows installation that supports WSL 2.
  • Docker Desktop, configured to use its WSL 2 backend.
  • Visual Studio Code, with the following extensions installed.
    • Dev Containers extension (ms-vscode-remote.remote-containers). This allows VS Code to connect to and work inside Docker development containers.
    • WSL (ms-vscode-remote.remote-wsl). This allows VS Code to open projects stored in your Ubuntu WSL filesystem.

Obvious statement: You’ll also need a Microsoft 365 tenant with SharePoint Online, for testing your WebPart in SharePoint.

You don’t need to install Node.js or Yeoman directly on Windows for the environment described here. Those tools will be installed in the container.

Configure Docker Desktop and WSL 2

If you haven’t already configured WSL 2, open Windows Terminal or PowerShell as an administrator and run:

wsl --install

This installs or enables WSL. Depending on your Windows setup, it may not install a Linux distribution automatically.

To install Ubuntu explicitly, run:

wsl --install -d Ubuntu

During the installation, create your initial username and password.

If you’d prefer a different distribution, list the available options with wsl --list --online and install your chosen one using wsl --install -d <DistributionName>

You can verify your installed distributions by running:

wsl --list --verbose

Install Docker Desktop and ensure that Use the WSL 2 based engine is enabled in its settings. Under Settings > Resources > WSL Integration. Turn on Enable integration with my default WSL distro, or tick the checkbox for your chosen distribution, if it appears in the list.

Start Docker Desktop and wait until it reports that the engine is running before continuing.

Install Visual Studio Code and add the Dev Containers and WSL extensions from the Extensions view.

Alternatively, install both extensions from Windows PowerShell:

code --install-extension ms-vscode-remote.remote-containers
code --install-extension ms-vscode-remote.remote-wsl

As mentioned above, the WSL extension allows VS Code to work directly with files stored in Ubuntu, while Dev Containers allows it to build and connect to our Docker-based SPFx development environment.

Fixing the VS Code UNC Host Warning

When opening a project stored in the WSL 2 filesystem, VS Code on Windows may display a warning similar to:

The host ‘wsl.localhost’ was not found in the list of allowed hosts.

This happens because VS Code restricts access to UNC paths unless the host has been explicitly allowed or approved. You can resolve the warning by adding wsl.localhost to VS Code’s allowed UNC hosts.

  • Open VS Code on Windows.
  • Press Ctrl+Shift+P and select Preferences: Open User Settings (JSON).
  • Add the following setting to settings.json, preserving any existing settings:
"security.allowedUNCHosts": [
    "wsl.localhost",
    "wsl$"
]
  • Save the file and restart VS Code.

If the warning persists, check that the setting was added to the Windows VS Code user settings and that the host name matches the one shown in the warning.

For more information, see the official VS Code documentation on working with UNC paths.

Verify that Docker is available from PowerShell:

docker --version
docker info

The last command should return information about the Docker engine rather than an error connecting to it.

Store your source code in the right place

For the best performance, keep your development files in the Linux filesystem managed by WSL 2 rather than directly under a Windows path such as C:\Users\....

For example, open your WSL distribution app (e.g Ubuntu) and create the initial folders for the project:

mkdir -p ~/dev/m365/spfx/projects
cd ~/dev/m365/spfx

This recommendation applies to Docker Desktop using WSL 2. Keeping files in the Linux filesystem helps avoid slower filesystem access and file-watching problems that can occur when Linux containers work with files stored on the Windows filesystem.

Create the development container

We’ll use a custom Docker image based on version 24.x of Node.js. It will install the tools needed to generate and build an SPFx project.

We’ll use VS Code Dev Containers to build and manage the development environment directly from a Dockerfile. This keeps the configuration separate from our source code, which will be stored in a dedicated projects directory.

From ~/dev/m365/spfx, create the following structure:

spfx/
├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
└── projects/

The projects directory will hold your SPFx solutions. The .devcontainer directory contains the files that define the development environment.

Create the Dockerfile

Create the .devcontainer directory and the projects directory if they don’t already exist, then create the Dockerfile:

mkdir -p .devcontainer
touch .devcontainer/Dockerfile

code .devcontainer/Dockerfile

Add the following to .devcontainer/Dockerfile:

FROM node:24-bookworm

RUN apt-get update \
    &amp;&amp; apt-get install -y --no-install-recommends \
        ca-certificates \
        git \
        openssh-client \
        openssl \
    &amp;&amp; rm -rf /var/lib/apt/lists/*

RUN npm install --global \
    yo \
    @microsoft/generator-sharepoint@1.24.1 \
    @rushstack/heft

WORKDIR /workspace
USER node

This image uses Node.js 24 LTS on Debian Bookworm. We’re using version 24 here but, obviously, other Node.js versions are supported and are listed in the Microsoft’s SPFx compatibility documentation. It installs:

  • Yeoman (yo), which runs the SPFx project generator.
  • The SPFx project generator, which creates the SharePoint Framework project structure.
  • Heft, the build toolchain used by SPFx 1.24 and later.
  • Git and OpenSSH client utilities for working with source control and SSH-based repositories.
  • OpenSSL, for working with development certificates.

The tools are installed globally in the image, and the container runs as the non-root node user.

We’ve pinned the SPFx generator to version 1.24.1 so that the environment uses a known generator release. The global Heft CLI is not pinned here, it installs the latest available version when the image is built. Individual SPFx projects also have their own local toolchain dependencies, which are managed through their package files and lockfile.

Create the Dev Container configuration

touch .devcontainer/devcontainer.json
code .devcontainer/devcontainer.json

Add the following to .devcontainer/devcontainer.json:

{
  "name": "SPFx Development",
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },
  "workspaceFolder": "/workspace",
  "workspaceMount": "source=${localWorkspaceFolder}/projects,target=/workspace,type=bind",
  "remoteUser": "node",
  "forwardPorts": [4321],
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint"
      ]
    }
  }
}

This configuration tells VS Code to build the development image using the Dockerfile in .devcontainer.

It also:

  • Mounts the local projects directory at /workspace inside the container.
  • Forwards port 4321, used by the SPFx development server, to the host.
  • Installs the ESLint extension in the container’s VS Code environment.

Forwarding port 4321 makes the local server accessible from the host, but it does not configure HTTPS certificate trust. You’ll configure and trust the development certificate later, before loading local manifests into a SharePoint page.

Open the project in the container

The Docker and Dev Container configuration is now in place. Next, open the workspace in VS Code.

From your WSL terminal, run:

code .

VS Code should open connected to your WSL distribution. If it opens in a local Windows context instead, install Microsoft’s WSL extension and reopen the folder from the WSL terminal.

In VS Code, open the Command Palette with Ctrl+Shift+P and select:

Dev Containers: Reopen in Container

VS Code will build the Docker image, create the development container and connect to it. The first build may take a little while because Docker needs to download the base image and install the development tools.

Once the process finishes, the VS Code terminal will run commands inside the container rather than directly in Windows or the WSL distribution.

Verifying the toolchain

Open a new terminal in VS Code and run the following to see the version of tools installed:

node --version
npm --version
yo --version
npm list --global --depth=0

Which will give an output similar to:

node --version
v24.22.2

npm --version
11.19.1

yo --version
7.0.1

npm list --global --depth=0
/usr/local/lib
├── @microsoft/generator-sharepoint@1.24.1
├── @rushstack/heft@1.3.5
├── corepack@0.36.0
├── npm@11.19.1
└── yo@7.0.1

Generate the SPFx WebPart

With the container running, open the terminal in VS Code and create a directory for the project:

mkdir my-spfx
cd my-spfx

Run the SPFx generator:

yo @microsoft/sharepoint

The generator will ask a series of questions. For a basic example, choose options along these lines:

PromptExample choice
Solution namemy-spfx
Target environmentSharePoint Online only (latest)
Component typeWebPart
WebPart nameMy WebPart
FrameworkReact

The available prompts can change between generator versions, so use the equivalent choices if the wording differs.

This downloads the packages defined by the generated project. The first installation may take several minutes.

Build the project

When generation completes, run the project’s build command:

npx heft build

If the build completes successfully, you’ve verified that the container can generate and compile an SPFx solution 🙂

You can inspect the generated package.json and run npm run to see the scripts available for that specific project. This is useful because the available scripts can vary by SPFx version and generator output.

At this point, you have a working development environment for creating SPFx solutions. Your project files remain in the mounted workspace, so you can commit them to Git and continue editing them from VS Code.

Run and test your SPFx WebPart

Building the project confirms that the development toolchain is working, but the next step is to run the WebPart and see it in SharePoint.

SPFx uses HTTPS for its local development server. Because the development server runs inside a Linux container while the browser runs on Windows, we need to make the container’s development certificate trusted by the Windows host as well.

1. Trust the development certificate

Before testing our SPFx solution in SharePoint Online, we need to configure Windows to trust the HTTPS certificate used by the local development server.

Why do we need to trust a certificate?

When we run heft start, SPFx starts a local HTTPS development server, normally accessible at:

https://localhost:4321

This server provides the JavaScript bundles, manifests and other resources needed to test our WebParts and extensions.

When debugging an SPFx WebPart on a SharePoint Online page, the browser loads the SharePoint page from Microsoft 365 but retrieves our development files from https://localhost:4321.

The local development server therefore needs to establish a trusted HTTPS connection.

SPFx uses a locally generated development certificate rather than one issued by a publicly trusted certificate authority. Because Windows and browsers don’t automatically trust this certificate, attempting to access the server may produce a certificate warning.

More importantly, the browser may refuse to load the development resources, preventing our WebPart from running correctly.

First, open the VS Code terminal connected to the container, if not already, and ensure you’re in the project directory:

cd /workspace/my-spfx

Run the Heft certificate task:

npx heft trust-dev-cert
 ---- trust-dev-cert started ---- 
[trust-dev-cert:trust-dev-cert] No development certificate found. Attempting to untrust the certificate and generate a new one.
[trust-dev-cert:trust-dev-cert] Automatic certificate untrust is only implemented for debug-certificate-manager on Windows and macOS. To untrust the development certificate, remove this certificate from your trusted root certification authorities: "/home/node/.rushstack/rushstack-serve.pem". The certificate has serial number "731c321744e34650a202e3ef91c3c1b0".
[trust-dev-cert:trust-dev-cert] Automatic certificate trust is only implemented for debug-certificate-manager on Windows and macOS. To trust the development certificate, add this certificate to your trusted root certification authorities: "/tmp/rushstacktpr5rxni23ntemp/1794151940628.pem".
[trust-dev-cert:trust-dev-cert] Certificate successfully trusted.
 ---- trust-dev-cert finished (0.306s) ---- 
-------------------- Finished (0.31s) --------------------

This command generates the SPFx development certificate inside the Linux container, under ~/.rushstack. You may see a message stating that automatic certificate trust is only supported on Windows and macOS. This is expected when running the command inside a Linux container and does not mean that certificate generation has failed.

Although Heft may report that the task completed successfully, this does not mean that Windows trusts the certificate. Our browser runs on Windows 11, outside the container, so we need to export the generated certificate and import it into the Windows Trusted Root Certification Authorities store.

We’ll do this in the next step.

From the project directory inside the dev container, run:

openssl x509 \
  -inform PEM \
  -in ~/.rushstack/rushstack-serve.pem \
  -outform DER \
  -out /workspace/spfx-dev-cert.cer

The certificate file is written to the project workspace, which is also mounted to the host. Note: the .cer file contains the public certificate, not the private key.

Open Windows PowerShell and change to your Windows-accessible project directory:

cd “\\wsl.localhost\Ubuntu\home\[your-username]\dev\m365\spfx\projects”

Then import the certificate:

Import-Certificate `
    -FilePath ".\spfx-dev-cert.cer" `
    -CertStoreLocation "Cert:\CurrentUser\Root"

If Windows displays a certificate installation confirmation, review the certificate details before accepting.

Should give a similar output to:

PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root

Thumbprint                                Subject
----------                                -------
3636A48ED96A984F829DA16E9D4F61363B65D2E2  CN=rushstack-certificate-manager.localhost

This imports the development certificate into your Trusted Root Certification Authorities store. You may need to restart your browser before it recognises the updated trust settings.

Once testing is complete, you can remove the exported .cer file from the project workspace so it isn’t accidentally committed to source control, add *.cer to your .gitignore file, or move somewhere else for safe-keeping.

2. Prepare a SharePoint page for testing

Microsoft is retiring the SharePoint Online hosted workbench on 1 December 2026. Instead of relying on the workbench, we’ll test the WebPart directly on a normal SharePoint Online page using the SharePoint Framework Debug Toolbar.

This approach lets you test your WebPart in a real SharePoint page and is also useful when developing SPFx extensions, which the workbench doesn’t support.

You’ll need access to a SharePoint Online tenant and a test site where you can edit pages.

Create or identify a modern SharePoint page on your test site. For example:

https://yourtenant.sharepoint.com/sites/dev/SitePages/SPFx-Test.aspx

Because our SPFx development server runs inside a Docker container, we need to ensure that it listens on an address that Docker can expose to Windows.

By default, a development server may listen only on localhost inside the container. This would restrict connections to processes running inside that same container, preventing our Windows browser from reaching the server through Docker’s forwarded port.

Open the generated ./config/serve.json file in your SPFx project and ensure that it includes the following settings.

{
  "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json",
  "port": 4321,
  "https": true,
  "ipAddress": "0.0.0.0",
  "initialPage": "https://yourtenant.sharepoint.com/sites/dev/SitePages/SPFx-Test.aspx"
}

This is an example configuration. Preserve any additional settings generated for your project.

The important settings are:

  • port: Specifies port 4321, which we’ve already forwarded in our devcontainer.json.
  • https: Enables HTTPS for the local development server.
  • ipAddress: Setting this to 0.0.0.0 tells the server to listen on all available network interfaces inside the container, allowing Docker to forward connections from Windows.
  • initialPage: Specifies the SharePoint page to open automatically when launching the development server.

Important: If your serve.json already contains a hostname setting, remove it when using ipAddress, as hostname will take precedence.

Since we’ll be starting the development server using npx heft start --nobrowser, configuring initialPage is optional. The –nobrowser switch prevents the development server from automatically launching a browser, and we’ll open our SharePoint test page manually in Windows instead.

Also note that 0.0.0.0 is a server listening address, not a browser URL. When accessing the development server from Windows, we’ll continue using https://localhost:4321.

When Heft starts, it may display a debugging URL containing 0.0.0.0. Replace that address with localhost when constructing the URL used by your Windows browser.

3. Start the development server

In the VS Code terminal connected to the container, ensure you’re in the project directory:

cd /workspace/my-spfx

Start the Heft development server:

npx heft start --nobrowser

The –nobrowser option prevents the container from trying to open a browser. Keep the terminal running while you test the WebPart.

The development server serves your local code over HTTPS. Make sure the certificate is trusted by the browser on Windows, as described in the previous section.

4. Load the WebPart on a SharePoint page

Open your test page in the Windows browser and append the following query-string parameters to its URL:

?debugManifestsFile=https://localhost:4321/temp/build/manifests.js&amp;debug=true&amp;noredir=true

For example:

https://yourtenant.sharepoint.com/sites/dev/SitePages/SPFx-Test.aspx?debugManifestsFile=https://localhost:4321/temp/build/manifests.js&amp;debug=true&amp;noredir=true

Use the URL path generated by your actual project if it differs from this example. The /temp/build/manifests.js path is important for the modern SPFx toolchain.

The debugManifestsFile parameter points it to the manifests served by your local development environment.

When prompted, allow the page to load debug scripts. Only enable these scripts when you’re intentionally testing your own development code.

Once the page loads in debug mode, the SharePoint Framework Debug Toolbar should appear.

Edit the page, select + to add a WebPart, and look for My WebPart and then add it to the page to test your locally served solution.

If you don’t see the WebPart, check that the development server is running, the certificate is trusted, and the manifest URL is correct.

5. Finish your debugging session

Keep the development server running while making changes to your code. Refresh the SharePoint page to test the updated solution.

When you’ve finished, use the Stop option in the Debug Toolbar to stop loading debug scripts for the current browser session, then close the page or remove the debugging query parameters.

Remember, this workflow loads your local development code into SharePoint. It doesn’t deploy the solution to your tenant or make it available to other users.

Conclusion

Docker and VS Code Dev Containers provide a repeatable SPFx development environment on Windows while keeping the Node.js toolchain inside a Linux container.

With the environment configured, you can generate, build and test SPFx WebParts without installing the full toolchain directly in Windows. The container configuration can also be shared with other developers to help them reproduce the same environment.

For further information, see Microsoft’s documentation on setting up the SPFx development environment, building your first WebPart and setting up a Microsoft 365 developer tenant.

Troubleshooting

The browser reports an untrusted certificate

Confirm that the certificate generated inside the container has been imported into the Windows user’s trusted root store. Make sure the certificate you imported is the one presented by the local server.

Note: Development certificates are stored inside the container under ~/.rushstack. If the container is removed and recreated, these files may be lost, causing RushStack to generate a new certificate. If that happens, you’ll need to export and import the replacement certificate into Windows again.

For a more permanent setup, you can mount the RushStack certificate directory to a persistent Docker volume or a directory outside the container. This allows certificates to survive container recreation, but isn’t necessary for the basic development environment I’ve described here.

The certificate is trusted, but SharePoint cannot load the local manifests

In newer versions of Microsoft Edge and Google Chrome, the browser may ask whether the SharePoint page is allowed to access devices or services on your local network.

Because SharePoint Online needs to load development resources from https://localhost:4321, you should allow this request when testing on your trusted SharePoint development site.

If you’ve previously denied permission, check the site’s permissions in your browser settings.

If the web part still doesn’t load, open the browser’s Developer Tools console and check for blocked requests or local network permission errors.

The certificate file cannot be found

Run npx heft trust-dev-cert inside the project and check that ~/.rushstack/rushstack-serve.pem exists. If the file is elsewhere, don’t assume the export command’s path is correct; locate the certificate generated by the toolchain.

The WebPart is missing from the SharePoint page

Check that npx heft start --nobrowser is still running and that the project builds successfully. Verify that the page URL includes debug=true and that debugManifestsFile points to https://localhost:4321/temp/build/manifests.js. Also confirm that the development certificate is trusted by your Windows browser and that you’ve allowed the page to load debug scripts.

The local development server cannot be reached

Confirm that the development server is running inside the container and that port 4321 is forwarded to the host. Check that the browser can access https://localhost:4321/temp/build/manifests.js without a certificate error. If it cannot, revisit the certificate trust steps and verify that the certificate installed in Windows matches the one used by the development server.

Don’t disable browser certificate validation to work around certificate errors.

Docker cannot connect to the engine

Make sure Docker Desktop is running and that the WSL 2 engine is enabled. From PowerShell, run:

docker info

If Docker reports that it cannot connect to the daemon, resolve that issue before trying to build the Dev Container.

The container build fails

Check the Dockerfile and ensure the image can access the package registry. You can also rebuild the Dev Container from VS Code using the Command Palette.

If an image tag or package version has changed or been removed, check the relevant official documentation before changing the pinned versions.

The build fails inside the generated project

Run the build from the generated project’s directory, not the workspace root:

cd /workspace/my-spfx
npx heft build

If it still fails, review the first error in the output and check the project’s Node.js and SPFx compatibility requirements.

File changes are slow or not detected

When using Docker Desktop with WSL 2, keep the project in the WSL filesystem rather than under /mnt/c or another Windows-mounted directory. Reopen the project from the WSL filesystem in VS Code.

This entry was posted in Development, Docker, SharePoint, SPFx, Visual Studio Code and tagged , . Bookmark the permalink.
0 0 votes
Article Rating
Subscribe
Notify of
guest

Solve the maths problem shown below before posting: *

0 Comments