Back to Dapr

Setup Dapr development environment using Visual Studio Code

docs/development/setup-dapr-development-using-vscode.md

1.17.610.0 KB
Original Source

Setup Dapr development environment using Visual Studio Code

This document helps you get started developing Dapr using VS Code. If you find any problems while following this guide, please create a Pull Request to update this document.

Using a development container in Visual Studio Code (VS Code)

VS Code supports development in a containerized environment through its Remote - Container extension, so you don't need to manually install all of the tools and frameworks needed to setup a Dapr development environment yourself.

Prerequisites

  1. Docker

    For Windows users, we recommend enabling WSL2 back-end integration with Docker.

  2. Visual Studio Code
  3. Visual Studio Code Remote - Containers extension

Using the Dapr development container

  1. After you have cloned the Dapr repo locally, open the dapr folder in VSCode. For example:

    bash
    git clone https://github.com/dapr/dapr.git
    cd dapr
    code .
    

    VS Code will detect the presence of a dev container definition in the repo and will prompt you to reopen the project in a container:

    Alternatively, you can open the command palette and use the Remote-Containers: Reopen in Container command.

  2. Once the container is loaded, open an integrated terminal in VS Code and you're ready to start Developing Dapr!

Customizing your dev container

The Dapr dev container is configured by default to support GitHub Codespaces, which you might want to change when running the dev container locally on your device.

Personalizing user settings in a dev container

VS Code supports applying your user settings, such as your .gitconfig, to a dev container through the use of dotfiles repositories. This can be done through your own VS Code settings.json file without changing the dev container image or configuration.

Using a custom dev container image

The Dapr devcontainer.json uses the latest image from the daprio Docker Hub, but you may need to modify the image destination to suit your host environment. For example, if you are using the devcontainer on a Linux host with a user whose UID is not 1000, you many need to remap the UID of the dapr user in the dev container to match your UID on the host.

  1. Edit the docker/Dockerfile-dev container image definition.

  2. Replace the "image" property with the commented-out "dockerFile" property in devcontainer.json to build and use the updated Dockerfile-dev file.

    json
    {
      "name": "Dapr Dev Environment",
      // Update container version when you update dev-container
      // "image": "docker.io/daprio/dapr-dev:0.1.7",
      // Replace with uncommented line below to build your own local copy of the image
      "dockerFile": "../docker/Dockerfile-dev",
      "runArgs": [
    ...
    
  3. Rebuild and reopen the workspace in the dev container via the command palette and the Remote-Containers: Rebuild and Reopen in Container command.

  4. When you are satisfied with your changes, you can optionally publish your container image to your own registry to speed up rebuilding the container when you only want to make changes to the devcontainer.json configuration in the future. For a Docker registry named myregistry:

    bash
    export DAPR_REGISTRY=myregistry
    make build-dev-container
    make push-dev-container
    

    And the devcontainer.json would be updated to restore the "image" property pointing to your own image:

    json
    {
      "name": "Dapr Dev Environment",
      // Update container version when you update dev-container
      "image": "docker.io/myregistry/dapr-dev:0.1.7",
      // Replace with uncommented line below to build your own local copy of the image
      // "dockerFile": "../docker/Dockerfile-dev",
      "runArgs": [
    ...
    

Sharing a Docker environment with localhost

The default Dapr dev container provides a Docker-in-docker configuration, so containers set up inside the dev container are not visible to the host and vice versa. This prevents the host environment from interfering with the dev container environment, for example, so that both the host and dev container can have separate standalone Dapr environments via dapr init.

If there are situations where you would like the dev container to share the Docker environment of the host or between multiple dev containers, you will likely want your dev container to be on the same network as your localhost, so you will need to update the "runArgs" property list to include the "--net=host" setting in devcontainer.json:

json
"runArgs": [
  ...

  // Uncomment to bind to host network for local devcontainer; this is necessary if using the
  // bind-mounted /var/run/docker-host.sock directly.
  "--net=host",

In addition, there are a couple of options for how you can expose the localhost Docker context to the dev container:

Create a Docker context for localhost in the dev container

The default devcontainer.json already maps a socket for the localhost Docker into the dev container, so you can take advantage of that by defining a Docker separate context for using it in the dev container:

⚠ If your localhost is a Linux system, note that the dev container is running as --privileged and these instructions can modify your privileges.

bash
sudo chown root:docker /var/run/docker-host.sock
docker context create host-context --description "Use localhost Docker environment" --docker "host=unix:///var/run/docker-host.sock"
docker context use host-context
docker ps

You should be able to see that the dev container itself is now visible in the list of running containers in the host-context. You can also use docker context use default to toggle back to using the Docker-in-docker configuration.

Rebind /var/run/docker.sock to localhost

If you don't want to use the Docker-in-docker configuration at all, you can chose to rebind the /var/run/docker.sock directly to the localhost socket so that the default Docker context is always the localhost. This can be done by enabling the BIND_LOCALHOST_DOCKER environment variable in the devcontainer.json file:

json
"containerEnv": {
  ...
  // Uncomment to disable docker-in-docker and automatically proxy default /var/run/docker.sock to
  // the localhost bind-mount /var/run/docker-host.sock.
  "BIND_LOCALHOST_DOCKER": "true"
},

This approach has the added benefit that it will use socat to proxy /var/run/docker-host.sock if it is owned by root on localhost, to avoid modifying localhost permissions on Linux hosts.

Cloning your Kubernetes configuration into the dev container

Since it is likely that contributors and maintainers will want to test Dapr changes against a Kubernetes environment, the Dapr dev container comes pre-installed with Kubernetes, Helm and Minikube for testing within the dev container environment.

If you want to reuse an existing Kubernetes config, such as your Azure Kubernetes Service config or local Minikube cluster, you can also configure the devcontainer.json copy those settings into the dev container as well. This requires:

  1. Enabling the SYNC_LOCALHOST_KUBECONFIG environment variable
  2. Bind mounting the locations of your Kubernetes and Minikube config paths to /home/dapr/.kube-localhost and /home/dapr/.minikube-localhost respectively.
    • You don't need to bind the Minikube path if you're not using it.
json
"containerEnv": {
  // Uncomment to overwrite devcontainer .kube/config and .minikube certs with the localhost versions
  // each time the devcontainer starts, if the respective .kube-localhost/config and .minikube-localhost
  // folders respectively are bind mounted to the devcontainer.
  "SYNC_LOCALHOST_KUBECONFIG": "true",
  ...
},

...

"runArgs": [
  ...
  // Uncomment to clone local .kube/config into devcontainer
  "--mount", "type=bind,source=${env:HOME}${env:USERPROFILE}/.kube,target=/home/dapr/.kube-localhost",

  // Uncomment to additionally clone minikube certs into devcontainer for use with .kube/config
  "--mount", "type=bind,source=${env:HOME}${env:USERPROFILE}/.minikube,target=/home/dapr/.minikube-localhost",
  ...
]

The SYNC_LOCALHOST_KUBECONFIG option only supports providing the dev container with the snapshot configuration from the host and does not support updating the host Kubernetes configuration from the dev container directly.

  • The copy happens on every boot of the dev container, so any changes on the host side are not captured after the dev container is started.
  • Any changes made to the dev container ~/.kube/config such as changing the default context or updating credentials are not reflected back to the host, even if it may have changed for the underlying environment (e.g. AKS credential updates).
  • If using Minikube, it needs to be started on the host before the dev container is launched. The Minikube configuration in the dev container is distinct from the host and cannot be used to start the host Minikube from inside the dev container. This option only supports cloning default Minikube credentials into the dev container for use by the Kubernetes config.
  • The copy will overwrite any previous state in the dev container with localhost settings, so do not use this option with the dev container's instance of Minikube.