<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>docker-desktop on Digi Hunch</title><link>https://static.digihunch.com/tag/docker-desktop/</link><description>Recent content in docker-desktop on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Tue, 08 Apr 2025 14:59:35 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/docker-desktop/index.xml" rel="self" type="application/rss+xml"/><item><title>Local multi-node cluster – Minikube, MicroK8s and KinD</title><link>https://static.digihunch.com/2021/09/single-node-kubernetes-cluster-minikube/</link><pubDate>Tue, 14 Sep 2021 11:18:00 -0400</pubDate><guid>https://static.digihunch.com/2021/09/single-node-kubernetes-cluster-minikube/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-multi-node-k8s.webp" alt="Featured image of post Local multi-node cluster – Minikube, MicroK8s and KinD" /&gt;&lt;p class="wp-block-paragraph"&gt;In this post we compare Minikube, MicroK8s and KinD as different approaches to build multi-node cluster locally.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="is-docker-desktop-bad"&gt;Is Docker desktop bad?&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the &lt;a href="https://static.digihunch.com/2021/08/docker-desktop-a-single-node-kubernetes-cluster/"&gt;previous post&lt;/a&gt; about docker desktop as a single-node Kubernetes cluster setup, I touched on the deprecation of docker-shim. Now that CRI beats OCI as the standard for container runtime, the docker runtime will no longer be supported by Kubernetes. Also deprecated is docker-shim, the temporary interface that had make Docker runtime work in Kubernetes. This was announced in December 2020, and is coming through in Kubernetes 1.23, expected Oct 2021. However, docker desktop still uses docker runtime in it&amp;#8217;s single-node Kubernetes cluster. This essentially renders itself a non-compliant Kubernetes environment. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker desktop still has great value for application developers. If your role is development, spending a lot of time coding business logics and need an easy-to-use container runtime on your laptop, Docker desktop is a good choice. The recent &lt;a href="https://www.docker.com/blog/updating-product-subscriptions/"&gt;moves&lt;/a&gt; by the company seems to suggest that this is the business they are targeting now. On the other hand, if your roles are deployment, automation, orchestration, cloud native etc and you are looking for a playground, most likely you do need a runtime compliant to Kubernetes CRI. Docker desktop is not a &lt;a href="https://www.cncf.io/certification/software-conformance/"&gt;CNCF-certified project&lt;/a&gt; anymore, and it is not your choice. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="alternatives"&gt;Alternatives&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are a number of alternatives, the most well-known ones are Minikube, MicroK8s, KinD and K3s with K3d. &lt;a href="https://www.cncf.io/wp-content/uploads/2020/08/CNCF-Webinar-Navigating-the-Sea-of-Local-Clusters-.pdf"&gt;This &lt;/a&gt;presentation from CNCF in 2020 covers a lot of details about these technologies. I&amp;#8217;ll try to add my opinion.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://rancher.com/docs/k3s/latest/en/"&gt;K3s&lt;/a&gt; is Rancher Lab&amp;#8217;s lightweight Kubernetes distribution that supports multi-node cluster as well as different runtimes (e.g. containerd). It is not straightforward to setup, and &lt;a href="https://k3d.io/"&gt;k3d&lt;/a&gt; is an command-line wrapper to make it easy to install K3s cluster. K3s was accepted as a &lt;a href="https://www.cncf.io/projects/k3s/"&gt;CNCF project &lt;/a&gt;but only at Sandbox maturity level, so it is not my choice. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The other three: Minikue, MicroK8s and KinD are all certified CNCF project. I will further discuss how to choose among them. These projects are technologies that takes different approach to address the challenges with deploying multiple nodes in local environment (e.g. my laptop). &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The challenge with running a Kubernetes cluster with multiple nodes locally is how to manage these nodes. They are separate virtual resources that need to be isolated from computing perspective, and connected as a cluster. This is typically the use case of a Type II &lt;a href="https://static.digihunch.com/2020/07/overview-of-virtualization/"&gt;hypervisor&lt;/a&gt;, or alternatively, it can also be implemented with container technology. This layer of technology (referred to as drivers) makes a big difference.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="minikube"&gt;Minikube&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Minikube supports multiple drivers. Depending on your platform (Windows, Linux, or MacOS), the preferred driver is different. Refer to the document &lt;a href="https://minikube.sigs.k8s.io/docs/drivers/"&gt;here&lt;/a&gt; for preferred driver, and this blog &lt;a href="https://kubernetes.io/blog/2019/03/28/running-kubernetes-locally-on-linux-with-minikube-now-with-kubernetes-1.14-support/"&gt;post&lt;/a&gt; for more instructions. In addition to the documents, here some notes from my personal experience:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;On MacOS, &lt;a href="https://minikube.sigs.k8s.io/docs/drivers/"&gt;Minikube&lt;/a&gt; lists Docker as preferred driver. I disagree with that. If you have no other reason to install &lt;strong&gt;Docker&lt;/strong&gt;, then I would recommend &lt;strong&gt;hyperkit&lt;/strong&gt; as the the preferred driver. Hyperkit can be installed with a simple &lt;strong&gt;Homebrew&lt;/strong&gt; command. For two reasons I do not recommend Docker as the driver of Minikube. First, it requires a separate installation of Docker Desktop, which includes a built-in instance of &lt;strong&gt;hyperkit&lt;/strong&gt; on its own. This isn&amp;#8217;t neat. Second, I often need Metal LB add-on with Minikube for testing Kubernetes Ingress. With Minikube on Docker, the Ingress ports are not exposed to MacOS&amp;#8217;s. Therefore you cannot directly visit websites spun up on Minikube. This is a &lt;a href="https://github.com/kubernetes/minikube/issues/7332"&gt;known issue&lt;/a&gt; for a while due to &lt;a href="https://github.com/kubernetes/minikube/issues/7332#issuecomment-608133325"&gt;limitation&lt;/a&gt; on docker &lt;a href="https://github.com/kubernetes/minikube/issues/13795"&gt;bridge&lt;/a&gt; with Mac. Some reported an ugly &lt;a href="https://github.com/kubernetes/minikube/issues/7332#issuecomment-1164452857"&gt;workaround&lt;/a&gt; with &lt;a href="https://github.com/chipmk/docker-mac-net-connect"&gt;docker-mac-net-connect&lt;/a&gt; but I never got it to work.&lt;/li&gt;&#10;&lt;li&gt;On Windows native environment, the preferred driver is hyper-V. The Minikube cli command have to run from Windows PowerShell. &lt;/li&gt;&#10;&lt;li&gt;On WSL2, Minikube doesn&amp;#8217;t play well, regardless of driver. The hyperkit driver won&amp;#8217;t work (it is designed for MacOS only). The kvm2 driver would require a KVM2 hypervisor. However, WSL2 itself is a VM on top of hypervisor, as explained &lt;a href="https://static.digihunch.com/2020/06/wsl2-environment-on-windows-10/"&gt;here&lt;/a&gt;. If KVM2 driver works it would require nested virtualization so I doubt it will ever be supported. As for Docker on WSL2 as driver, Minikube has it as an &lt;a href="https://minikube.sigs.k8s.io/docs/drivers/docker/"&gt;experimental feature&lt;/a&gt;, and requires configuring cgroup to allow setting memory. I am not confident with it.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To me, Minikube is the tool for MacOS (I have Intel processor). On MacOS, we first need to install minikube and hyperkit with home brew.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We can then start a kubernetes cluster, with minikube in a single command. I noticed a process on my MacBook called dnscrypt-proxy that conflicts with hyperkit DNS server when starting minikube. I had to remove dnscrypt-proxy (part of Cisco Umbrella Roaming Client) in order to get minikube to work, as &lt;a href="https://github.com/kubernetes/minikube/issues/3036"&gt;this&lt;/a&gt; thread suggests. You can find out by running:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo lsof -i :53&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If dnscrypt-proxy is running, find out the application by PID and remove the application. Otherwise there will be issues. Check out &lt;a href="https://minikube.sigs.k8s.io/docs/drivers/hyperkit/#local-dns-server-conflict"&gt;this&lt;/a&gt; section on the document. The commands that I use to start multi-node cluster is:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;minikube start --driver&lt;span style="color:#f92672"&gt;=&lt;/span&gt;hyperkit --container-runtime&lt;span style="color:#f92672"&gt;=&lt;/span&gt;containerd --memory&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;12288&lt;/span&gt; --cpus&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; --disk-size&lt;span style="color:#f92672"&gt;=&lt;/span&gt;150g --nodes &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get po -A&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl describe node minikube|grep Runtime&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Node administration is simple. To enable dashboard, simply run &amp;#8220;minikube dashboard&amp;#8221;. To SSH to a node, simply do &amp;#8220;minikube ssh -n &amp;lt;node_name&amp;gt;&amp;#8221;. In order to stop the node and delete cluster, run &amp;#8220;minikube stop &amp;amp;&amp;amp; minikube delete&amp;#8221;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are some addons in minikube, for example, efk, gvisor, istio, metrics-server. To list add-ons, and enable metrics-server, for example, run:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;minikube addons list&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;minikube addons enable metrics-server&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When creating cluster, instead of specifying the cluster imperatively, the configuration (e.g. driver, container runtime, cpu, memory, number of nodes, etc) can be stored as a &lt;a href="https://minikube.sigs.k8s.io/docs/commands/profile/"&gt;profile&lt;/a&gt; with -p switch. Like other Minikube configuration information, Minikube profiles are stored in ~/.minikube under the profile directory.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Minikube also has a &lt;a href="https://minikube.sigs.k8s.io/docs/benchmarks/imagebuild/minikubevsothers/"&gt;page&lt;/a&gt; that benchmarks the performance of these technologies, where it presents itself as the most performant.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://minikube.sigs.k8s.io/images/benchmarks/minikubeVsOthers/iterative.png" alt="Iterative Loads"/&gt;&lt;figcaption class="wp-element-caption"&gt;Minikube, KinD, k3d and microK8s performance&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;h3 class="wp-block-heading" id="microk8s"&gt;MicroK8s&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;MicroK8s is developed by Canonical. It can use either Multipass or LXD container as driver. Multipass can configure Ubuntu VMs using cloud-init. It supports multiple hypervisor backends as well but hyperkit is the default on MacOS, Hyper-V on Windows, and KVM on Linux.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;MicroK8s supports multi-node configuration across multiple machines. That is, nodes can span across multiple physical machines. This is more powerful than Minikube where multiple nodes are on the same physical machine. It brings MicroK8s additional use cases such as edge and IoT devices.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With that capability comes the extra step to configure a MicroK8s cluster. You will need to manually join a node to a cluster because the new node is potentially located on a different machine, and you execute the command from the new machine. On the other hand, with Minikube you simply specify the number of nodes desired in a command or profile.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Snap is the native package manager to install MicroK8s, making GNU Linux (e.g. Ubuntu) the native platform. It also supports MacOS and Windows. MicroK8s does not rely on Docker (unlike KinD and Minikube with Docker as driver), and uses containerd as runtime.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://microk8s.io/docs/working-with-kubectl"&gt;MicroK8s&lt;/a&gt; comes with its own packaged version of kubectl, and you use that with &amp;#8220;microk8s kubectl&amp;#8221; command, which is not convenient. You can configure your host kubectl to point to the MicroK8s cluster, as an extra step.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Compared to the other two technologies, MicroK8s is more powerful in the sense that the cluster is build on nodes across multiple machines. However, it takes more step to configure even for a multi-node, single-machine environment. Refer to &lt;a href="https://kubernetes.io/blog/2019/11/26/running-kubernetes-locally-on-linux-with-microk8s/#:~:text=Microk8s%20is%20the%20click%2Dand,doesn't%20require%20a%20VM."&gt;this&lt;/a&gt; post for the steps.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="kind"&gt;KinD&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;KinD is similar to Minikube with Docker as driver. It is more restricted than Minikube considering Docker is the only driver it supports. This makes it a requirement to have Docker installed locally.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Although KinD uses Docker to run nodes, it does not use Docker as its container runtime. Therefore it remains as compliant environment.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Another advantage of KinD is it supports Docker on &lt;a href="https://kind.sigs.k8s.io/docs/user/using-wsl2/"&gt;WSL2&lt;/a&gt; very well. Simply install KinD on WSL2 and start Docker. This blog &lt;a href="https://kubernetes.io/blog/2020/05/21/wsl-docker-kubernetes-on-the-windows-desktop/"&gt;post&lt;/a&gt; contains the steps required to install KinD vs Minikube on WSL2. There is a comparison table in the conclusion section that highlights the fact that it is much easier to install KinD with WSL2 than to install Minikube.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;However, there are currently some &lt;a href="https://docs.docker.com/desktop/windows/networking/#known-limitations-use-cases-and-workarounds"&gt;known limitations&lt;/a&gt; with Docker desktop for Windows (including on WSL2). One is the absence of docker0 bridge. This means on Windows you cannot route traffic to the containers.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For cluster specification, KinD can configure a cluster declaratively using YAML file for example, the kind-config.yaml contains the following snippet:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Cluster&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;kind.x-k8s.io/v1alpha4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;nodes&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;role&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;control-plane&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;role&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;worker&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;role&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;worker&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;role&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;worker&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;networking&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;disableDefaultCNI&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;We can bring up a cluster with a command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind create cluster --config&lt;span style="color:#f92672"&gt;=&lt;/span&gt;kind-config.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command will also configure the kubectl context so we can check node with kubectl command. The file is in my &lt;a href="https://github.com/digihunch/real-quicK-cluster/tree/main/kind"&gt;real-quicK-cluster&lt;/a&gt; repo.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="conclusion"&gt;Conclusion&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;After reviewing the technologies that back up multi-node kubernetes cluster for my role, I find that Minikube with hyperkit is my favourite for MacOS. On WSL2, I prefer to use KinD. Since I do not use Windows native environment or Ubuntu on my laptop, I cannot make recommendations. However I would start with Minikube (with hypverv or kvm2 as driver). &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Update July 2022&lt;/strong&gt;: When the test workload involves persistent storage, KinD is a better choice. When the test workload involves load balancer. Minikube is a better choice.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As to storage provisioner, Minikube with storage-provisioner addon uses k8s.io/&lt;a href="https://github.com/kubernetes/minikube/tree/master/deploy/addons/storage-provisioner"&gt;minikube-hostpath&lt;/a&gt;. KinD uses &lt;a href="https://github.com/rancher/local-path-provisioner"&gt;rancher.io/local-path&lt;/a&gt;. When I have to test workload with persistent storage (e.g. PostgreSQL with &lt;a href="https://access.crunchydata.com/documentation/postgres-operator/v5/"&gt;Crunchy pgo&lt;/a&gt;), I realized Minikube have permission issues with persistent volume, as discussed &lt;a href="https://github.com/kubernetes/minikube/issues/12360"&gt;here&lt;/a&gt; as an issue with multiple nodes. The issue has been open since Aug 2021.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For Load Balancer, Minikube has metallb as an addon and I can configure it within a &lt;a href="https://github.com/digihunch/real-quicK-cluster/blob/main/minikube/restart-minikube.sh"&gt;bash script&lt;/a&gt; conveniently. With KinD, I&amp;#8217;d have to configure that in a few &lt;a href="https://kind.sigs.k8s.io/docs/user/loadbalancer/"&gt;steps&lt;/a&gt; with both kubectl and Docker CLI commands and I was not able to connect to the load balancer by IP even after following the steps. So I tend to just use Minikube to test workload requiring load balancer and service mesh. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I find myself switch between Minikube and KinD on my MacBook depending on the test workload.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/09/log-shipping-in-kubernetes-with-efk/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Log Shipping in Kubernetes with EFK stack&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/09/file-storage-vs-object-storage/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;File storage vs object storage in the cloud&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Single-node Kubernetes cluster – docker desktop</title><link>https://static.digihunch.com/2021/08/docker-desktop-a-single-node-kubernetes-cluster/</link><pubDate>Sun, 22 Aug 2021 00:24:00 -0400</pubDate><guid>https://static.digihunch.com/2021/08/docker-desktop-a-single-node-kubernetes-cluster/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-single-node-k8s.webp" alt="Featured image of post Single-node Kubernetes cluster – docker desktop" /&gt;&lt;p class="wp-block-paragraph"&gt;While there are many tools to set up single-node Kubernetes cluster (e.g. &lt;a href="https://minikube.sigs.k8s.io/docs/start/"&gt;minikube&lt;/a&gt;, &lt;a href="https://microk8s.io/"&gt;MicroK8s&lt;/a&gt;, &lt;a href="https://kind.sigs.k8s.io/docs/user/quick-start/"&gt;kind&lt;/a&gt;, or &lt;a href="https://k3s.io/"&gt;k3s&lt;/a&gt; with the &lt;a href="https://k3d.io/"&gt;k3d&lt;/a&gt; wrapper), docker-desktop has a significant advantage: it comes with Docker installation, on MacOS, or on Windows. It is installed simply by enabling the option &amp;#8220;Enable Kubernetes&amp;#8221;. It can be blown away and reset in a heartbeat (with the button &amp;#8220;Reset Kubernetes Cluster&amp;#8221;). For its versatility, docker-desktop is a great development environment.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;However, there are always nuances, which motivates me to write this blog. I wanted to note down what is on earth different about Docker-desktop, because the instructions for applications might differ slightly between single-node cluster on MacOS/Windows and the &amp;#8220;real&amp;#8221; multi-node cluster. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I will start with with a deep dive into the docker-desktop architecture, then we&amp;#8217;ll go through the steps to install some common applications with Kubernetes.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-docker-desktop-on-macos"&gt;Docker-Desktop on MacOS&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are a number of open-source and proprietary projects involved to bring docker-desktop to implementation. Let&amp;#8217;s begin with the following five:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;a href="https://developer.apple.com/documentation/hypervisor"&gt;Hypervisor Framework&lt;/a&gt;: Apple&amp;#8217;s APIs on MacOS that allows you to interact with virtualization technologies in user space.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://wiki.freebsd.org/bhyve"&gt;bhyve&lt;/a&gt;: A type-2 hypervisor initially written for FreeBSD (and was contributed to FreeBSD in May 2011).&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/machyve/xhyve"&gt;xhyve&lt;/a&gt;: A port of bhyve project to MacOS with integration via Apple&amp;#8217;s Hypervisor Framework. The Hypervisor Framework allows xhyve to run entirely in userspace. It is sometimes loosely referred to as xhyve/bhyve hypervisor, and is optimized for lightweight virtual machines and container deployment.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/moby/hyperkit"&gt;HyperKit&lt;/a&gt; is an open-source toolkit on macOS based on xhyve. HyperKit is lightweight and therefore allows you to embed hypervisor capabilities in your application. The hypervisor component in HyperKit is based on xhyve/bhyve. HyperKit is designed to be interfaced with higher-level components such as the VPNKit and DataKit. Docker-desktop and &lt;a href="https://minikube.sigs.k8s.io/docs/drivers/hyperkit/"&gt;MiniKube&lt;/a&gt; are built on HyperKit.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/moby/hyperkit"&gt;LinuxKit&lt;/a&gt; is a toolkit for building custom minimal, immutable and purpose-build Linux distributions. It supports several well-known hypervisor platforms, such as HyperKit, Hyper-V, qemu and VMware. &lt;a href="https://www.docker.com/blog/introducing-linuxkit-container-os-toolkit/"&gt;LinuxKit&lt;/a&gt; started as an internal project in Docker Inc and is now managed as a &lt;a href="https://mobyproject.org/"&gt;Moby Project&lt;/a&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hyperkit is installed as part of docker desktop. The process can be found with ps command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ps -Af | grep hyperkit&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Or in the activity monitor:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="942" height="303" src="https://static.digihunch.com/wp-content/uploads/2021/08/image-3.png" alt="" class="wp-image-2648"/&gt;&lt;figcaption class="wp-element-caption"&gt;Docker related processes&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker-deskop is essentially a LinuxKit virtual machine (as defined &lt;a href="https://github.com/linuxkit/linuxkit/blob/master/examples/docker-for-mac.yml"&gt;here&lt;/a&gt;). It runs containerd process inside of the virtual machine. &lt;a href="https://collabnix.com/how-docker-for-mac-works-under-the-hood/"&gt;This&lt;/a&gt; is an older article about this architecture. If Kubernetes is enabled, the virtual machine is also installed with kubelet, the agent process running on each Kubernetes node.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Since MacOS is not the direct host of the containers, there is no way to map MacOS file system to container&amp;#8217;s as you can with a Docker/Kubernetes host. Prior to Docker 20.10, there used to be a &lt;a href="https://timonweb.com/docker/getting-path-and-accessing-persistent-volumes-in-docker-for-mac/"&gt;trick&lt;/a&gt; to indirectly access host volume from MacOS terminal. It has stopped working according to &lt;a href="https://github.com/docker/for-mac/issues/4822"&gt;this&lt;/a&gt; issue but workarounds are provided &lt;a href="https://stackoverflow.com/questions/63445657/why-i-am-getting-screen-is-terminating-error-in-macos/63595817#63595817"&gt;here&lt;/a&gt;. This &lt;a href="https://gist.github.com/BretFisher/5e1a0c7bcca4c735e716abf62afad389#2021-update-easiest-option-is-justins-repo-and-image"&gt;post&lt;/a&gt; proposes some good alternatives to access the file system of LinuxKit VM. For example, use netcat:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; user@LinVM &lt;span style="color:#75715e"&gt;# nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/ &lt;span style="color:#75715e"&gt;# cat /etc/os-release&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /etc/os-release&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRETTY_NAME&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Docker Desktop&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/ &lt;span style="color:#75715e"&gt;# cat /etc/kubernetes/current-version&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /etc/kubernetes/current-version&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubeadm version: &amp;amp;version.Info&lt;span style="color:#f92672"&gt;{&lt;/span&gt;Major:&lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, Minor:&lt;span style="color:#e6db74"&gt;&amp;#34;21&amp;#34;&lt;/span&gt;, GitVersion:&lt;span style="color:#e6db74"&gt;&amp;#34;v1.21.2&amp;#34;&lt;/span&gt;, GitCommit:&lt;span style="color:#e6db74"&gt;&amp;#34;092fbfbf53427de67cac1e9fa54aaa09a28371d7&amp;#34;&lt;/span&gt;, GitTreeState:&lt;span style="color:#e6db74"&gt;&amp;#34;archive&amp;#34;&lt;/span&gt;, BuildDate:&lt;span style="color:#e6db74"&gt;&amp;#34;2021-06-18T05:24:26Z&amp;#34;&lt;/span&gt;, GoVersion:&lt;span style="color:#e6db74"&gt;&amp;#34;go1.16.5&amp;#34;&lt;/span&gt;, Compiler:&lt;span style="color:#e6db74"&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;, Platform:&lt;span style="color:#e6db74"&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Typing in this terminal session feels clunky. According to this &lt;a href="https://stackoverflow.com/questions/64530530/how-may-i-connect-to-a-docker-desktop-virtual-machine-on-mac-docker-desktop-ve"&gt;thread&lt;/a&gt;, we can connect to the LinuxKit VM with tty and sane auto completion, using the command below:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stty -echo -icanon &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; stty sane&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;There are some other alternatives, using privileged Docker containers:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -it --privileged --pid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;host debian nsenter -t &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; -m -u -n -i sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The following command uses a smaller image:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -it --rm --privileged --pid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;host justincormack/nsenter1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;As with Kubernetes, to access the file system on the node is via a privileged container, you can follow the &lt;a href="https://docs.microsoft.com/en-us/azure/aks/ssh"&gt;tips&lt;/a&gt; from Azure, identify node name, and debug against the node using a special container:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl debug node/docker-desktop -it --image&lt;span style="color:#f92672"&gt;=&lt;/span&gt;mcr.microsoft.com/aks/fundamental/base-ubuntu:v0.0.11&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note that the root directory on the host is mounted to container&amp;#8217;s file system as /host. This mapping renders a lot of symbolic link as dangled, even though they are actually not on the host file system. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-docker-desktop-on-windows"&gt;Docker-Desktop on Windows&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker works with Linux kernel. There have been a couple of efforts to run Linux virtual machine on Windows. For example, Hyper-V backend, and Windows Subsystem Linux (WSL) backend.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Traditionally, Docker on Windows was implemented with Hyper-V as the hypervisor. A LinuxKit distro is running on the Hypver-V VM, provider Linux kernel capabilities. Docker refers to containers running in this architecture as &amp;#8220;Windows Containers&amp;#8221;, which is a misnomer in my opinion.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The first release of &lt;a href="https://www.zdnet.com/article/under-the-hood-of-microsofts-windows-subsystem-for-linux/"&gt;WSL &lt;/a&gt;provides a Linux-compatible kernel interface and runs a GNU user space on top of the interface. Neither the Linux kernel code, or a hypervisor is involved. The user space contains GNU Bash shell, command language, command-line tools and interpreters. The absence of Linux kernel in WSL, makes it useless for Docker setup. At that time The Hypver-V backend was still the only option to host docker container during the first version of WSL. This &lt;a href="https://www.docker.com/blog/new-docker-desktop-wsl2-backend/"&gt;post &lt;/a&gt;has a diagram of Docker on Windows with Hyper-V backend.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="741" height="192" src="https://static.digihunch.com/wp-content/uploads/2021/08/image-1.png" alt="" class="wp-image-2616"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://static.digihunch.com/2020/06/wsl2-environment-on-windows-10/"&gt;WSL2&lt;/a&gt; comes with a real Linux Kernel (also on top of Hyper-V), making WSL2 a better alternative than the legacy Hyper-V as the backend of Docker on Windows. It can be turned on as the screenshot shows above. The rest of this post assumes WSL2 as backend. In this setup, we run a Bootstrapping distro independent of the WSL2 Linux distro, although both inside of the lightweight Linux Utility VM. Below is the diagram:&lt;/p&gt;&#10;&lt;p class="has-text-align-center wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="691px" viewBox="-0.5 -0.5 691 371" style="max-width:100%;max-height:371px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="690" height="370" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;rect x="10" y="30" width="150" height="230" fill="#fad9d5" stroke="#ae4132" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 27px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Windows&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="27" fill="#000000" font-family="Helvetica" font-size="17px" text-anchor="middle"&gt;Windows&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="10" y="280" width="650" height="70" rx="10.5" ry="10.5" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 648px; height: 1px; padding-top: 315px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Hypervisor (Hyper-V)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="335" y="320" fill="#000000" font-family="Helvetica" font-size="17px" text-anchor="middle" font-weight="bold"&gt;Hypervisor (Hyper-V)&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="170" y="30" width="490" height="230" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 488px; height: 1px; padding-top: 27px; margin-left: 171px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Lightweight Linux Utility VM&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="415" y="27" fill="#000000" font-family="Helvetica" font-size="17px" text-anchor="middle" font-weight="bold"&gt;Lightweight Linux Utility VM&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="190" y="180" width="450" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 448px; height: 1px; padding-top: 210px; margin-left: 191px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;WSL2 Linux Kernel&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="415" y="215" fill="#333333" font-family="Helvetica" font-size="17px" text-anchor="middle" font-weight="bold"&gt;WSL2 Linux Kernel&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="30" y="180" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 210px; margin-left: 31px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;NT Kernel&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="90" y="215" fill="#333333" font-family="Helvetica" font-size="17px" text-anchor="middle" font-weight="bold"&gt;NT Kernel&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="30" y="80" width="120" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 110px; margin-left: 31px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Windows Usermode&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="90" y="115" fill="#000000" font-family="Helvetica" font-size="17px" text-anchor="middle"&gt;Windows Usermo&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="190" y="70" width="250" height="80" fill="#d5e8d4" stroke="#82b366" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 110px; margin-left: 191px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;&lt;div&gt;WSL2-compatible Linux Distro&lt;/div&gt;&lt;div&gt;in Usermode (e.g. Ubuntu)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="315" y="115" fill="#000000" font-family="Helvetica" font-size="17px" text-anchor="middle"&gt;WSL2-compatible Linux Distro&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="470" y="70" width="170" height="80" fill="#d5e8d4" stroke="#82b366" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 110px; margin-left: 471px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 17px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Docker desktop&lt;br&gt;(Bootstrapping distro)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="555" y="115" fill="#000000" font-family="Helvetica" font-size="17px" text-anchor="middle"&gt;Docker desktop&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 414.96 274.61 L 414.99 246.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 414.95 279.86 L 411.46 272.86 L 414.96 274.61 L 418.46 272.87 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 415 241.12 L 418.49 248.12 L 414.99 246.37 L 411.49 248.11 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 555.67 173.63 L 555.18 156.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 555.82 178.88 L 552.12 171.98 L 555.67 173.63 L 559.12 171.79 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 555.03 151.12 L 558.73 158.02 L 555.18 156.37 L 551.73 158.21 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 249.88 173.63 L 249.97 156.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 249.86 178.88 L 246.39 171.86 L 249.88 173.63 L 253.39 171.9 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 249.99 151.12 L 253.46 158.14 L 249.97 156.37 L 246.46 158.1 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 156.37 110 L 183.63 110" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 151.12 110 L 158.12 106.5 L 156.37 110 L 158.12 113.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 188.88 110 L 181.88 113.5 L 183.63 110 L 181.88 106.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 90 73.63 L 90 60 Q 90 50 100 50 L 545 50 Q 555 50 555 56.82 L 555 63.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 90 78.88 L 86.5 71.88 L 90 73.63 L 93.5 71.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 555 68.88 L 551.5 61.88 L 555 63.63 L 558.5 61.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 446.37 110 L 463.63 110" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 441.12 110 L 448.12 106.5 L 446.37 110 L 448.12 113.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 468.88 110 L 461.88 113.5 L 463.63 110 L 461.88 106.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 90 146.37 L 90 173.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 90 141.12 L 93.5 148.12 L 90 146.37 L 86.5 148.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 90 178.88 L 86.5 171.88 L 90 173.63 L 93.5 171.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 89.84 246.37 L 89.16 273.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 89.97 241.12 L 93.3 248.2 L 89.84 246.37 L 86.3 248.03 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 89.03 278.88 L 85.7 271.8 L 89.16 273.63 L 92.7 271.97 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;/g&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Viewer does not support full SVG 1.1&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The innovative component is the lightweight Linux Utility VM. It is called a VM, but very different from the traditional sense of VM such as VirtualBox or VMware. Traditional VM is isolated from host OS, slow to boot and has large memory footprint. The lightweight Utility VM on the other hand, is integrated with host OS, super fast to boot (i.e. ~1 second), and comes with small memory footprint. It is not turned on until needed. The VM runs both a WSL2 Linux Kernel and GNU/Linux usermode (known as &amp;#8220;distribution&amp;#8221;, for example, Ubuntu). When an end-user say WSL2, s/he most likely refers to the distribution. Similarly, the so called &amp;#8220;docker-desktop on Windows with WSL2 backend&amp;#8221;, is also managed as two WSL2 distros: the bootstrapping distro (docker-desktop) and the data store distro (docker-desktop-data). &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The detailed components in the Bootstrapping distro is in the second diagram in &lt;a href="https://www.docker.com/blog/new-docker-desktop-wsl2-backend/"&gt;this &lt;/a&gt;post, which has a detailed discussion. With this architecture, you don&amp;#8217;t even need the WSL2 Linux Distro for Docker desktop to function. You can even run docker CLI command from Windows PowerShell without any Linux distro (although this is implemented only for backward compatibility and not recommended anymore) . In the following session, we first list out the WSL2 distros. Notice that the docker-desktop distro is not the default. We then connect to the distro using -d switch. Last, we run docker info from windows user space.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\WINDOWS\system32&amp;gt; wsl -l -v&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NAME STATE VERSION&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;* Ubuntu Running &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; docker-desktop Running &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; docker-desktop-data Running &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\WINDOWS\system32&amp;gt; wsl -d docker-desktop&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WINLAPTOP&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;/mnt/host/c/WINDOWS/system32&lt;span style="color:#75715e"&gt;# cd ~&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WINLAPTOP&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;~&lt;span style="color:#75715e"&gt;# printenv|grep DIST&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WSL_DISTRO_NAME=docker-desktop&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WINLAPTOP&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;~&lt;span style="color:#75715e"&gt;# exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\WINDOWS\system32&amp;gt; docker info&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Client&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Context&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Debug Mode&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Plugins&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; buildx&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; Build with BuildKit (Docker Inc., v0.5.&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;-docker)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; compose&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; Docker Compose (Docker Inc., v2.0.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;-beta.&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scan&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; Docker Scan (Docker Inc., v0.8.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Server&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Containers&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;93&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Running&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Paused&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Stopped&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Images&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Server Version&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20.10&lt;/span&gt;.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Storage Driver&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; overlay2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Backing Filesystem&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; extfs&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Supports d_type&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Native Overlay Diff&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; userxattr&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Logging Driver&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; json-file&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Cgroup Driver&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; cgroupfs&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Cgroup Version&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Plugins&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Volume&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; local&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Network&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; bridge host ipvlan macvlan null overlay&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Log&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Swarm&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; inactive&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Runtimes&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; io.containerd.runc.v2 io.containerd.runtime.v1.linux runc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Default&lt;/span&gt; Runtime&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; runc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Init Binary&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; docker-init&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; containerd version&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; d71fcd7d8303cbf684402823e425e9dd2e99285d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; runc version&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; init version&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; de40ad0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Security Options&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; seccomp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Profile&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Kernel Version&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5.10&lt;/span&gt;.16.&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;-microsoft-standard-WSL2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Operating System&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; Docker Desktop&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; OSType&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; linux&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Architecture&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; x86_64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; CPUs&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Total Memory&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;.32GiB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Name&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; docker-desktop&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ID&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; WHDE&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;PJF3&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;HVFC&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;AZJA&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;EDKH&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;VUZR&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;RRUJ&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;HHXX&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;TDV5&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;4UJG&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;XY4E&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;PK4F&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Docker Root Dir&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; /var/lib/docker&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Debug Mode&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Registry&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; https&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;//index.docker.io/v1/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Labels&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Experimental&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Insecure Registries&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;127.0&lt;/span&gt;.0.&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;/&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Live Restore Enabled&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; false&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The wsl -d command as illustrated above is a good way to connect to the docker-desktop distro. The alternative to get to the distro is via privileged container (Docker) or helper pod (Kubernetes), which is the same as in Docker-desktop on MacOS. Refer to the section above for specific steps.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-application-install-on-docker-desktop"&gt;Application Install on docker desktop&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The followings are my notes to install commonly used applications in Docker Desktop with Kubernetes. They work on both MacOS or WSL2, requiring Kubernetes enabled.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-metric-server"&gt;Metric server&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The metric server is provided in the &lt;a href="https://github.com/kubernetes-sigs/metrics-server"&gt;official&lt;/a&gt; repository. Releases are publish &lt;a href="https://github.com/kubernetes-sigs/metrics-server/releases/latest"&gt;here&lt;/a&gt;, which provides the installation step as follows:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.5.0/components.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;However, there is some issues when deploying it on MacOS, the deployment will fail due to certificates not matching the hostname. To fix the issue, it is recommended to download the yaml file (components.yaml), and edit the file by adding &amp;#8211;kubelet-insecure-tls to the args section of the container named &lt;em&gt;metrics-server&lt;/em&gt;. This is sufficient to fix the issue. Some people are not comfortable with port 443 being insecure TLS, and would rather change the port to 4443. This is completely unnecessary but if that&amp;#8217;s the case, make sure the named port for https is also updated to 4443.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Once metric server has been installed, the following two commands should return meaningful results:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl top no&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl top po&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This should also allow application (Pods) to query for cluster resource usage. When working with single-node cluster on MacOS or WSL2, multiple Pods might come up with a single command and the memory can be easily over-subscribed. The two commands above allows you to check and make adjustment on the node configuration (in Docker preference).&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-dashboard"&gt;Dashboard&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Similar to metric server, the dashboard is kept in the official &lt;a href="https://github.com/kubernetes/dashboard"&gt;repo&lt;/a&gt;, in the the path of aio/deploy/recommended.yaml. &lt;a href="https://github.com/kubernetes/dashboard/releases/latest"&gt;Here&lt;/a&gt; is the published release, where the instruction says:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;However, this is not directly applicable either because the login page requires token or kubeconfig. We need to be able to bypass that. To do so, download the yaml file (recommended.yaml), and add parameter &amp;#8211;enable-skip-login to the args section for the container named &lt;em&gt;kubernetes-dashboard&lt;/em&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To display the login page properly, we need to start the proxy using this command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl proxy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The login page will then be available at &lt;a href="http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/"&gt;this&lt;/a&gt; URL. The URL reflects the namespace and service name. On the login page, the skip button will be available.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-rancher"&gt;Rancher&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The official installation guide of Rancher 2.5x recommends RKE Kubernetes. If you prefer not to run a separate cluster on MacOS, you can install it on docker desktop (with Kubernetes enabled). The installation steps require Helm 3 and are completed in three helm commands.&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Install Nginx Ingress controller using Helm, following the three commands &lt;a href="https://kubernetes.github.io/ingress-nginx/deploy/#using-helm"&gt;here&lt;/a&gt;. Alternatively, you can apply the rendered template as posted &lt;a href="https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.48.1/deploy/static/provider/cloud/deploy.yaml"&gt;here&lt;/a&gt;. The controller will later be used by the ingress that Rancher&amp;#8217;s chart creates.&lt;/li&gt;&#10;&lt;li&gt;Follow the steps on &lt;a href="https://ranchermanager.docs.rancher.com/getting-started/installation-and-upgrade/install-upgrade-on-a-kubernetes-cluster"&gt;this&lt;/a&gt; page to install Rancher, even though the page does not say it applies to docker desktop. If you do not have TLS certificate, the Rancher helm chart can generate one for you, using cert-manager.&lt;/li&gt;&#10;&lt;li&gt;The installation exposes rancher application on port 443 of the MacBook, and the cert is issued to &amp;#8220;rancher.my.org&amp;#8221; by default. To access it, add &amp;#8220;127.0.0.1 rancher.my.org&amp;#8221; to the host file.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To back out from the steps above, just uninstall with helm. For example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm uninstall rancher -n cattle-system&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm uninstall cert-manager -n cert-manager&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm uninstall ingress-nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 class="wp-block-heading" id="h-jenkins"&gt;Jenkins&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Similar to Rancher, Jenkins instruction assumes minikube cluster instead of docker desktop.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo add jenkinsci https://charts.jenkins.io&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo update&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl create namespace jenkins&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install jenkins -n jenkins -f https://raw.githubusercontent.com/jenkinsci/helm-charts/main/charts/jenkins/values.yaml jenkinsci/jenkins&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl --namespace jenkins port-forward svc/jenkins 8080:8080&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;To find out the default password for admin user:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl -n jenkins get secrets jenkins -o jsonpath&lt;span style="color:#f92672"&gt;={&lt;/span&gt;.data.jenkins-admin-password&lt;span style="color:#f92672"&gt;}&lt;/span&gt; | base64 -D&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;To uninstall Jenkins:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm uninstall jenkins -n jenkins&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 class="wp-block-heading" id="h-container-runtime"&gt;Container Runtime&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Although I seem to be a proponent of docker desktop thus far, this post would be incomplete to not discuss what is missing with docker desktop. One key difference between docker desktop and minikube is the container runtime being used. Docker desktop uses docker as the runtime, and it does not support other runtime as of now. Minikube allows user to choose runtime, including containerd. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Because of this difference, Kubernetes nodes with Docker as runtime and with containerd as runtime place pod log files in different locations. To find out the runtime, use the following command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl describe node &amp;lt;node_name&amp;gt; | grep Runtime&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If the runtime is docker, the stdout of container is placed in /var/lib/docker/containers/&amp;lt;sha&amp;gt;/. If the runtime is containerd, the stdout log of pods are stored in /var/log/containers/. This is important to know when you configure log shipping and needs to get stdout from node. The log path used in containerd is the standard path in compliance with Container Runtime Interface (CRI) so you should develop log shipping solution based on that.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker&amp;#8217;s refusal to comply to CRI also caused Kubernetes to stop supporting it as container runtime as of Dec 2020. For more background, refer to &lt;a href="https://kubernetes.io/blog/2020/12/02/dockershim-faq/"&gt;this&lt;/a&gt; and &lt;a href="https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/"&gt;this&lt;/a&gt;. &lt;a href="https://ink.insertcoin.dev/news/dockershim-deprecation"&gt;Here&lt;/a&gt; is also an article with great diagrams on the removal of docker-shim.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-bottom-line"&gt;Bottom line&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker-desktop is a great tool for a quick single-node Kubernetes environment. As of docker 20.10, docker-desktop still uses docker as runtime. This limits its use case to development only. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If you need a CRI compliant environment, docker-desktop is not a good choice. We will discuss alternatives in the next post.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/08/scalable-infrastructure-deployment-in-terraform/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Infrastructure deployment in Terraform 1/2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/08/creating-tls-certificate-kubernetes/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Creating X.509 TLS certificate for workload on Kubernetes&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Setup WSL2 (and Docker) on Windows 10</title><link>https://static.digihunch.com/2020/06/wsl2-environment-on-windows-10/</link><pubDate>Tue, 02 Jun 2020 22:01:00 -0400</pubDate><guid>https://static.digihunch.com/2020/06/wsl2-environment-on-windows-10/</guid><description>&lt;p class="wp-block-paragraph"&gt;This is not for Linux snobs, but rather for those who are stuck with a Windows work laptop, have to deal with Linux on a daily basis, and are not a fan of PuTTY. This posting provides the steps to setup Windows 10 so you get a work environment closer to a Linux one. The environment to begin with should be Windows 10 version 2004 and above in order to use WSL2. &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/compare-versions"&gt;Here&amp;#8217;s &lt;/a&gt;the comparison between WSL and WSL2. This &lt;a href="https://www.youtube.com/watch?v=lwhMThePdIo"&gt;presentation &lt;/a&gt;is a great deep dive into how WSL2 works. The architecture diagram below is from that presentation. Note that WSL2 operates on a &amp;#8220;true&amp;#8221; Linux Kernel, therefore giving WSL2 the ability to run Docker.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://4.bp.blogspot.com/-e_FaEsP7nH8/Xca4QMFtjQI/AAAAAAAAERA/r59YN5UCXlwdNsfPNy-sjjyTQ4o_dtbjACLcBGAsYHQ/s1600/wsl1-wsl2.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;h3 class="wp-block-heading" id="h-install-wsl2"&gt;Install WSL2&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;WSL2 was officially released in Windows 10 version 2004 (build 19041 or higher) and we will use Ubuntu 20.04 LTS. If you&amp;#8217;re upgraded from older version of Windows 10 you will need to upgrade. The steps are:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Install Ubuntu 20.04 LTS from Microsoft Store, which requires Windows components &amp;#8220;Windows Subsystem for Linux&amp;#8221; and &amp;#8220;Virtual Machine Platform&amp;#8221;; or, if you already have an older version of Ubuntu such as 18.04, you will need to run a distribution upgrade with &amp;#8220;sudo apt-get dist-upgrade&amp;#8221;;&lt;/li&gt;&#10;&lt;li&gt;Upgrade Linux Virtual Machine from WSL to WSL2, following the official instruction &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10"&gt;here&lt;/a&gt;; Once completed, use this command to confirm the WSL version installed: wsl.exe &amp;#8211;list -v&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" width="634" height="104" src="https://static.digihunch.com/wp-content/uploads/2020/06/image-1.png" alt="" class="wp-image-1056" style="width:317px;height:52px"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There&amp;#8217;s also plenty of Youtube videos with step-by-step instruction on upgrading to WSL2 and its advantage over WSL. Once you&amp;#8217;re there, you will realize one problem: the command terminal for Ubuntu is ugly:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="2318" height="622" src="https://static.digihunch.com/wp-content/uploads/2020/06/image.png" alt="" class="wp-image-1055"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The colour looks awful and it does not support multi-tabs. If you want better palette, there are a number of options. Check out &lt;a href="https://github.com/Microsoft/Terminal/tree/master/src/tools/ColorTool"&gt;ColorTool&lt;/a&gt; project and &lt;a href="https://github.com/mbadolato/iTerm2-Color-Schemes"&gt;iTerms2 Colors&lt;/a&gt; project. The former gives you away to configure color scheme (from command prompt but takes effect in WSL as well) and the latter gives you rich choices of color schemes. My personal favourite is &amp;#8220;Banana Blueberry&amp;#8221;. The command to set color scheme is: &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;C:\ColorTool.exe -b &amp;#34;iTerm2-Color-Schemes-master\schemes\Banana Blueberry.itermcolors&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 class="wp-block-heading" id="h-windows-terminal"&gt;Windows Terminal&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For a better terminal, consider Windows Terminal from Microsoft Store. &lt;a href="https://github.com/microsoft/terminal"&gt;Windows terminal&lt;/a&gt; is an open-source project and still a little &lt;a href="https://github.com/microsoft/terminal/issues/4448"&gt;glitchy&lt;/a&gt; as of June 2020. However it is heading to the right direction. Once installed, you may customize it by clicking settings:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1066" height="412" src="https://static.digihunch.com/wp-content/uploads/2020/06/image-3.png" alt="" class="wp-image-1058"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A json file will open and you may edit it for customization, for example, you can adjust each profile (e.g. PowerShell, Windows command or WSL); you can specify default profile and default open location. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// This file was initially generated by Windows Terminal 1.0.1401.0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// It should still be usable in newer versions, but newer versions might have additional&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// settings, help text, or changes that you will not see unless you clear this file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// and let us generate a new one for you.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// To view the default settings, hold &amp;#34;alt&amp;#34; while clicking on the &amp;#34;Settings&amp;#34; button.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// For documentation on these settings, see: https://aka.ms/terminal-documentation&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;$schema&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://aka.ms/terminal-profiles-schema&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;defaultProfile&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{2c4de342-38b7-51cf-b940-2309a097f518}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// You can add more global application settings here.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about global settings, visit https://aka.ms/terminal-global-settings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// If enabled, selections are automatically copied to your clipboard.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;copyOnSelect&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// If enabled, formatted data is also copied to your clipboard&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;copyFormatting&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// A profile specifies a command to execute paired with information about how it should look and feel.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Each one of them will appear in the &amp;#39;New Tab&amp;#39; dropdown,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// and can be invoked from the commandline with `wt.exe -p xxx`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about profiles, visit https://aka.ms/terminal-profile-settings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;profiles&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;defaults&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Put settings here that you want to apply to all profiles.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;list&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{2c4de342-38b7-51cf-b940-2309a097f518}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Ubuntu&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;source&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Windows.Terminal.Wsl&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startingDirectory&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;//wsl$/Ubuntu/home/myuser/&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Make changes here to the powershell.exe profile.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{61c54bbd-c2c6-5271-96e7-009a87ff44bf}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Windows PowerShell&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;commandline&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;powershell.exe&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Make changes here to the cmd.exe profile.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0caa0dad-35be-5f56-a8ff-afceeeaa6101}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Command Prompt&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;commandline&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;cmd.exe&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{b453ae62-4e3d-5e58-b989-0a998ec441b8}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Azure Cloud Shell&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;source&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Windows.Terminal.Azure&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Add custom color schemes to this array.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about color schemes, visit https://aka.ms/terminal-color-schemes&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;schemes&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Add custom keybindings to this array.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To unbind a key combination from your defaults.json, set the command to &amp;#34;unbound&amp;#34;.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about keybindings, visit https://aka.ms/terminal-keybindings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;keybindings&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Copy and paste are bound to Ctrl+Shift+C and Ctrl+Shift+V in your defaults.json.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// These two lines additionally bind them to Ctrl+C and Ctrl+V.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about selection, visit https://aka.ms/terminal-selection&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;action&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;copy&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;singleLine&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+c&amp;#34;&lt;/span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;paste&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+v&amp;#34;&lt;/span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Press Ctrl+Shift+F to open the search box&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;find&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+shift+f&amp;#34;&lt;/span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Press Alt+Shift+D to open a new pane.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// - &amp;#34;split&amp;#34;: &amp;#34;auto&amp;#34; makes this pane open in the direction that provides the most surface area.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// - &amp;#34;splitMode&amp;#34;: &amp;#34;duplicate&amp;#34; makes the new pane use the focused pane&amp;#39;s profile.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about panes, visit https://aka.ms/terminal-panes&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: { &lt;span style="color:#e6db74"&gt;&amp;#34;action&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;splitPane&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;split&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;auto&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;splitMode&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;duplicate&amp;#34;&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;alt+shift+d&amp;#34;&lt;/span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;With these configuration, we have a quite comfortable Linux work environment on Windows.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-update-to-zsh-and-beautify-it"&gt;Update to Zsh and beautify it&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I&amp;#8217;m no so big a fan of zsh (for lack of default &lt;a href="https://superuser.com/questions/584249/using-wildcards-in-commands-with-zsh/740728"&gt;wildcard support&lt;/a&gt;) but I do like one of its themes. We can install zsh on WSL2 (assuming Ubuntu distribution). This is a good &lt;a href="https://blog.nillsf.com/index.php/2020/02/17/setting-up-wsl2-windows-terminal-and-oh-my-zsh/"&gt;instruction&lt;/a&gt;. I do like the theme name agnoster. However, the theme displays username at the beginning of the prompt, which takes a lot of screen real estate if your username is long. To remove it, the trick is to add a line in ~/.zshrc, as answered in &lt;a href="https://stackoverflow.com/questions/28491458/zsh-agnoster-theme-showing-machine-name/38295938#:~:text=You%20can%20set%20DEFAULT_USER%3D%22%5B,the%20%5Buser%20name%5D%20value.&amp;amp;text=This%20will%20negate%20the%20%22%24user%22%20!%3D"&gt;this&lt;/a&gt; thread. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-docker-runtime"&gt;Docker runtime&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There is a lot of fun to have in WSL2 on Windows 10. For example, you can configure Docker runtime on Windows according to &lt;a href="https://nickjanetakis.com/blog/a-linux-dev-environment-on-windows-with-wsl-2-docker-desktop-and-more"&gt;this post&lt;/a&gt;. However, you cannot route traffic to the container in the absence of docker0 bridge for Docker on WSL2, as indicated in the &lt;a href="https://docs.docker.com/desktop/windows/networking/#known-limitations-use-cases-and-workarounds"&gt;known limitations&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Update: Docker also brings a Kubernetes cluster named docker-desktop. This allows you configure Kubernetes cluster, or install &lt;a href="https://static.digihunch.com/2021/07/helm-configuration-management-for-kubernetes-resources/"&gt;Helm&lt;/a&gt; and Rancher (&lt;a href="https://rafalfaro.medium.com/how-to-install-rancher-2-5-in-docker-desktops-bundled-kubernetes-cluster-ebd5e1b0ae8"&gt;instruction&lt;/a&gt;) for cluster management.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-dual-boot"&gt;Dual-Boot?&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With WSL2 on top of a real Linux kernel, I do not find a need for a dual-boot system on my workstation. To be fair, only in the following scenarios should one consider installing a dual-boot system.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;You need to work on a specify version of Linux Kernel. The kernel provided by Microsoft is called &amp;#8220;microsoft-standard-WSL2&amp;#8221;, and its pretty up to date (5.x)&lt;/li&gt;&#10;&lt;li&gt;You need to run GUI applications on Linux. Update: Microsoft has started developing GUI application support on WSL2, even though it usually takes time to mature.&lt;/li&gt;&#10;&lt;li&gt;You need to work on a distribution not available in Windows Store. WSL2 provides a kernel and it&amp;#8217;s up to developers to provide Linux distros in Windows store. Popular (and official) ones are: Ubuntu 20.04 LTS by Canonical Group, Debian by the Debian project, SUSE Linux Enterprise Server by SUSE, Kali Linux.&lt;/li&gt;&#10;&lt;li&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Certificate Issuers&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I have to use WSL2 mostly because I&amp;#8217;m forced to use a Windows laptop on my contracts. That also means that the Windows laptop has been configured to corporate firewall&amp;#8217;s packet inspection. When that is the case, they corporate IT usually automatically imports a firewall certificate to the Windows trust store. However, the WSL is missing this certificate. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The symptom would be that you cannot run certain curl command. For example, when I do the followings:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -LO &lt;span style="color:#e6db74"&gt;&amp;#34;https://dl.k8s.io/release/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;curl -L -s https://dl.k8s.io/release/stable.txt&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/bin/linux/amd64/kubectl&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl: &lt;span style="color:#f92672"&gt;(&lt;/span&gt;60&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SSL certificate problem: unable to get local issuer certificate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;More details here: https://curl.se/docs/sslcerts.html&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl failed to verify the legitimacy of the server and therefore could not&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;establish a secure connection to it. To learn more about this situation and&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;how to fix it, please visit the web page mentioned above. &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This error message basically means that the website certificate cannot be trusted. To view the certificate, use Open SSL command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl s_client -connect dl.k8s.io:443 -servername dl.k8s.io | openssl x509 -text -noout | less&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In my case, I noticed that the certificate is a Zscaler issued certificate (firewall). While running the same command from my personal device returns a Goolge Trust issued certificate. This indicates that the certificate is changed by the proxy managed by the corporation. To fix this I need to export the certificate from Windows, and then import it in WSL. The &lt;a href="https://stackoverflow.com/questions/72167566/wsl-docker-curl-60-ssl-certificate-problem-unable-to-get-local-issuer-certi"&gt;answer&lt;/a&gt; in this post has good detailed steps.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/05/ansible-directory-for-scalability-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Ansible at scale 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/06/network-analyzer-capture-filter-and-display-filter/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Capture filter and Display filter in Network Analyzer&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>