DEV Community

Cover image for How To Install Docker Without Docker Desktop On Windows
Paul Knulst
Paul Knulst

Posted on • Updated on • Originally published at paulsblog.dev

How To Install Docker Without Docker Desktop On Windows

Paul Knulst  in  Docker • Oct 6, 2022 • 9 min read


As a developer who switched from Linux to Windows because of many reasons, I have used Docker Desktop for several months now because it updates my Docker environment automatically.

Unfortunately, this is not possible anymore and I have to remove Docker Desktop.

Luckily I did not use Docker Desktop for any commands or functionality except for updating the Docker engine so this change will not affect my workflow.

Why Should You Install Docker Without Docker Desktop?

Docker updated its Docker Desktop License Agreement and permit the professional use of Docker Desktop in large organizations without having a paid Docker subscription. This means that if your company has 250+ employees or more than $10 million in annual revenue you will not able to use Docker Desktop without a paid subscription. It remains free for smaller companies, private use, open-source projects, and educational purposes.

This license update is only related to Docker Desktop and not to Docker or the Docker Engine. This enables you to still use Docker for development and all types of environments, including the production ones. Normally, this license update does not impact your company’s business if working with Docker.

Prerequisites

To follow this How-To you need to have a WSL2 compatible workstation like Windows 10 version 2004 or higher. To check which version is installed press Windows logo key + R and press Enter to show your system settings. If you do not meet the requirement please update your Windows.

If Docker Desktop is installed you have to uninstall it

In Windows, the Linux Subsystem has to be enabled. This can be done by pressing the *Windows log key*, typing “Turn Windows features on and off” and open it.

Deactivate Windows Feature To Install Docker Without Docker Desktop On Windows
Screenshot from Windows start menu taken by the author

Scroll to the bottom and activate the feature if it is deactivated.

WSL2 Windows Feature should be activated to Install Docker Without Docker Desktop On Windows
Screenshot of Windows Features menu taken by the author

After activating press OK and restart your computer.


You can also install the Linux Subsystem with a PowerShell command:

    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enter fullscreen mode Exit fullscreen mode

Install Ubuntu on WSL2

After you set up the prerequisite you have to open a PowerShell with administrative privileges and install Ubuntu in WSL2 with the following command:

    wsl --set-default-version 2
    wsl --install -d Ubuntu
Enter fullscreen mode Exit fullscreen mode

You can also install different Linux submodules within this step.

After the installation is finished you should check if Ubuntu was installed in the correct version:

    wsl -l -v
Enter fullscreen mode Exit fullscreen mode

If everything worked correctly you should see your installed Ubuntu with the corresponding WSL version. If the version is not correct you can change it with:

    wsl --set-version Ubuntu-YY.MM 2
Enter fullscreen mode Exit fullscreen mode

YY.MM is the version of the Ubuntu version that you installed recently.

Install Docker

To install Docker on Windows within the Ubuntu submodule you can follow the official steps for installing Docker on Ubuntu:

Another way will be to create a new file and copy the following script into it. These commands are only copied from the official tutorial into a file to share with fellow developers

    #/bin/bash 

    # 1. Required dependencies 
    sudo apt-get update 
    sudo apt-get -y install apt-transport-https ca-certificates curl gnupg lsb-release 

    # 2. GPG key 
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg 

    # 3. Use stable repository for Docker 
    echo \ 
      "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ 
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 

    # 4. Install Docker 
    sudo apt-get update 
    sudo apt-get -y install docker-ce docker-ce-cli containerd.io 

    # 5. Add user to docker group 
    sudo groupadd docker 
    sudo usermod -aG docker $USER 
Enter fullscreen mode Exit fullscreen mode

Switch to your Ubuntu submodule within PowerShell and execute the file to install Docker and the needed dependencies.


You can now start and check if everything runs correctly with:

    sudo service docker start   # start the engine
    sudo service docker status  # print some nice status information
    docker run hello-world      # run a test docker container
Enter fullscreen mode Exit fullscreen mode

After the last command finish, you should see the running Docker image output:

    Hello from Docker! This message shows that your installation appears to be working correctly.

    To generate this message, Docker took the following steps:

    The Docker client contacted the Docker daemon.
    The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
    The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
    The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
    To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash

    Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/

    For more examples and ideas, visit: https://docs.docker.com/get-started/
Enter fullscreen mode Exit fullscreen mode

Common Problems with Ubuntu WSL2 Distro

If you install Ubuntu as your WSL2 Distro and use at least one that is based on Ubuntu Hirsute Hippo (21.04) it could happen that your docker daemon will not start correctly.

When trying to run dockerd it will produce the following error log:

    ...
    INFO[2021-09-25T15:06:20.839195000+08:00] Loading containers: start.
    INFO[2021-09-25T15:06:20.885624800+08:00] stopping event stream following graceful shutdown  error="<nil>" module=libcontainerd namespace=moby
    INFO[2021-09-25T15:06:20.885865900+08:00] stopping healthcheck following graceful shutdown  module=libcontainerd
    INFO[2021-09-25T15:06:20.886012400+08:00] stopping event stream following graceful shutdown  error="context canceled" module=libcontainerd namespace=plugins.moby
    failed to start daemon: Error initializing network controller: error obtaining controller instance: unable to add return rule in DOCKER-ISOLATION-STAGE-1 chain:  (iptables failed: iptables --wait -A DOCKER-ISOLATION-STAGE-1 -j RETURN: iptables v1.8.7 (nf_tables):  RULE_APPEND failed (No such file or directory): rule in chain DOCKER-ISOLATION-STAGE-1
     (exit status 4))
Enter fullscreen mode Exit fullscreen mode

I noticed that iptables being used by docker is a nftables version. This led to an error because starting from version 20.10 Ubuntu switched the firewall system to nftables (you can read about it on this website). Unfortunately, using nftables natively requires Linux Kernel 5.8 but the latest Kernel version for the WSL is 5.4.

Luckily, Ubuntu still has the possibility to use a legacy version of iptables by simply executing:

    $ sudo update-alternatives --config iptables

    There are 2 choices for the alternative iptables (providing /usr/sbin/iptables).

      Selection    Path                       Priority   Status
    ------------------------------------------------------------
    * 0            /usr/sbin/iptables-nft      20        auto mode
      1            /usr/sbin/iptables-legacy   10        manual mode
      2            /usr/sbin/iptables-nft      20        manual mode

    Press <enter> to keep the current choice[*], or type selection number: 1
    update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode
Enter fullscreen mode Exit fullscreen mode

After updating the iptables just restart the Docker daemon and you will notice that Docker starts working correctly.

Install Docker Compose

Installing Docker Compose can be done within the Ubuntu submodule. Open a PowerShell window and switch to the Ubuntu submodule. Then download the latest release from GitHub:

    sudo curl -L https://github.com/docker/compose/releases/download/2.4.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
Enter fullscreen mode Exit fullscreen mode

Next, grant privileges for execution to the docker-compose command:

    sudo chmod +x /usr/local/bin/docker-compose
Enter fullscreen mode Exit fullscreen mode

Afterward, you can test the functionality by executing docker-compose -version within the Ubuntu submodule or wsl docker-compose -version from any PowerShell window.

How To Integrate Docker And Docker Compose Into Your PowerShell

If you follow the tutorial you should have:

  1. WSL2 Linux subsystem installed
  2. Installed & configured Docker on Ubuntu
  3. Installed Docker Compose

You are able to use all Docker commands inside your Ubuntu submodule and also within a PowerShell by preceding the command with wsl:

    wsl docker ps
    wsl docker-compose -version
Enter fullscreen mode Exit fullscreen mode

For convenience, you should be able to use any Docker command without adding wsl in front of it. To achieve this you can create an alias for your PowerShell. Read about it here and set up everything.

Then find your PowerShell profile

    echo $PROFILE
Enter fullscreen mode Exit fullscreen mode

and open this file in an editor and paste this content:

    Function Start-WslDocker {
        wsl docker $args
    }
    Function Start-WslDockerCompose {
        wsl docker $args
    }
    Set-Alias -Name docker -Value Start-WslDocker
    Set-Alias -Name docker-compose -Value Start-WslDockerCompose
Enter fullscreen mode Exit fullscreen mode

Save the file and restart your PowerShell terminal to test if the alias is working by typing:

    docker ps
    docker-compose -version
Enter fullscreen mode Exit fullscreen mode

If you don’t get an error it works as expected.

Installing Portainer

To better replace Docker Desktop and have something like a Docker GUI you should install Portainer in your local environment.

Portainer is a powerful, GUI-based Container-as-a-Service solution that helps organizations manage and deploy cloud-native applications easily and securely.

With Portainer you can:

  1. Deploy applications with defined app templates (Click to Deploy)
  2. Deploy and Manage Stacks from Compose files, including deploying directly from the git
  3. Deploy & Manage Containers, including the ability to edit a running container
  4. Pull/Push/Build Images
  5. Create Networks
  6. Create/Delete Volumes
  7. See a log of Docker Events
  8. See docker engine (Host) information, and apply security controls should you desire

This Docker Compose file can be used to install Portainer CE as a Docker service that automatically is restarted if it is not running.

    version: '3'

    services:
      portainer:
        image: portainer/portainer-ce:latest
        container_name: portainer
        restart: unless-stopped
        security_opt:
          - no-new-privileges:true
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /var/run/docker.sock:/var/run/docker.sock:ro
          - ./portainer-data:/data
        ports:
          - 9000:9000
Enter fullscreen mode Exit fullscreen mode

Save it to any folder and run it in your PowerShell:

    docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Switch to your browser and open http://localhost:9000.

*Timing Note:* Make sure you log in and create your credentials soon after Portainer is ready, or it will automatically shut down itself for security. If you didn’t create the credentials on time and it shut down automatically, you have to restart the service.

Pros/Cons Of This Solution

Pros

There are multiple advantages compared to the Docker Desktop version:

  1. The Docker engine is free. So the license update won’t be a problem for your development and production environment.
  2. Portainer is a production-ready software to manage your Docker environment that also often is used in a server cluster environment.
  3. You will learn Docker basics much faster and will gain more DevOps competencies.
  4. Often production environments run in Linux so your development environment comes close to the production environment.

Cons

The only disadvantage for me is that you have to update it manually by yourself instead of pressing an “OK” button if a new version is available.

Closing Notes

Thanks for reading this article!

I hope you enjoyed reading it and are now able to install the Docker environment on your Windows Host within the Ubuntu submodule. Also, I hope that you can now use and install Portainer and Docker Compose on Windows. If it is working for you I would love to get your feedback in the comment section. Also, if you have any questions, please jot them down below. I will answer them if possible.

This article was published on my blog at https://www.paulsblog.dev/how-to-install-docker-without-docker-desktop-on-windows/

Feel free to connect with me on my personal blog, Medium, LinkedIn, Twitter, and GitHub.


Did you find this article valuable? Want to support the author? (... and support development of current and future tutorials!). You can sponsor me on Buy Me a Coffee or Ko-Fi. Furthermore, you can become a free or paid member by signing up to my website. See the contribute page for all (free or paid) ways to say thank you!


Photo by Alesia Kazantceva / Unsplash

Top comments (7)

Collapse
 
kkm000 profile image
Cy "kkm" K'Nelson • Edited

Paul, thank you for writing a detailed walkthrough! I'd like to add a few points:

  • If all you want is Docker, Ununtu is an overkill. Debian is a better choice, it's а stable server distro. I've been in fact using it on all my headless VMs and hardware machines, and WSL too. My gripe with Ubuntu is the incessant deluge of updates. Objectively, it has a smaller VHDX footprint, but if you Docker, that would be lost in the noise :) Just an opinion, but since you haven't asked... :)
  • WSL2 kernels 5.10 and 5.15 are available: learn.microsoft.com/en-us/windows/... but only for supported Windows versions. W10 2004 aka 20H1 Home and Pro have expired; Enterprise/Edu aren't yet. I think the kernels would probably work anyway on it.
  • To the “Pros” of WSL2, while it's just a non-Contra, I'd add that WSL2 integrates with both Visual Studio and VS Code all the same, you don't lose it if transition from Docker for Desktop, but need certain extension for VSCode. I mostly do C++ in VS on WSL2, as I specifically need Linux. Docker container development on WSL2 in both VS and VSCode. A tutorial for VSCode: learn.microsoft.com/en-us/windows/... Read the topmost green box about self-installed Docker on WSL2, as the tutorial lists steps for configuring Docker Desktop, which you ignore.
  • If you transfer files between a WSL2 instance and the host: The filesystem of every WSL2 instance is exposed under \\wsl$ as if it were a network server. Only running distros are available in this container in Explorer. The connection uses local sockets and is very fast. Either of [Win]+[R] \\wsl$ [Enter] and [Win]+[E] [Alt]+[D] \\wsl$ [Enter] gets you there. For command line or scripting, there is a quirk: in cmd/PS dir \\wsl$ doesn't work (this is udefined for UNC names; you normally use new view to list “shares”, but it doesn't work either), but a more specific e.g., dir \\wsl$\Debian does. Debian here stands for the distro NAME in the wsl -l -v command output. Or get it from Explorer \\wsl$.
  • Advanced: Where's the data? The instance uses a single VHDX virtual disk, located in $env:LOCALAPPDATA\Packages\<distro_package>\LocalState directory. Find the long and ugly <distro_package> with e.g. dir $env:LOCALAPPDATA\Packages\*debian*, or *canonical* for Ubuntu. You may need this location to check the VHDX file size, back it up (wsl --shutdown first!), exclude it from the main backup, or even move LocalState to another drive and softlink it (mklink /D command in cmd only, PS pre 7.1 can't, 7.1+ can but cumbersome, with new-item). Secure the new location if sensitive data (e.g., SSH keys) exist in your WSL2. See Get-Acl and Set-Acl in Powershell. Pipe the former into the latter to copy the security descriptor from the old directory to the new one.
  • WSL2 limits the filesystem to 256G by default. This limit is configurable, RTFM.
Collapse
 
paulknulst profile image
Paul Knulst • Edited

Thank you for adding this enormous amount of information. I really appreciate the work you put in this comment!!!

  • Kernel update is nice to know. I will keep an eye on it. I guess this is already fixed if I "reinstall" everything. I initially wrote this tutorial in February. Also I have Enterprise/Edu Windows at work/home.

  • I normally use Linux for most of my Docker instances because I run a Docker Swarm, or precisley Docker in swarm mode :-D. Local Docker Env is only to test before I deploy them. I don't like having weird localhost urls while in production I use Traefik, Swarm, etc.

  • This guide was mainly targeted for coworkers that have to switch and are not familiar with Linux/CLI. That's why I choose Ubuntu. It could be installed easily from the Microsoft AppStore and everyone at least knows Ubuntu ^^

  • I don't use VSCode. Mainly use console or JetBrains products :-D

  • For the data, I use a much simpler approach to move it. I just export the disk, unregister my distro and import the data again in the new location. That was one of the first things I researched while I started with Docker one year ago. I found it weird that its not like linux in /var/lib/docker ^^. See here my funny I start with Docker experience: paulsblog.dev/personal-experience-...

Anyway, thanks for your additions!

Collapse
 
kkm000 profile image
Cy "kkm" K'Nelson

Glad you found my notes helpful!

I chose Ubuntu. It could be installed [...] from the Microsoft AppStore

So is Debian. Ubuntu is in fact Debian-based. What sets them apart is their philosophy.
Debian targets, above all, stability, never upgrading even minor version points after release. It maintains a separate package feed, "backports," for explicit version upgrades; these are never considered for 'apt upgrade' automatically. I usually pick only a few tools, like git, which actually sprout useful features over the distro's biannual cadence period.
Ubuntu, on the other hand, shoots for the variety and recency of packages. I've been bitten not once by their impatient agility. The last thing I need between rebuilds while debugging an elusive, hard-to-repro issue, which I may have to put away for a couple weeks, is a minor-point upgrade of the libfoo5-dev package...

Matter of preference, naturally. Not advocating. Main point is Debian is also available in Store. There are quite a few other Linux-based ones. Run wsl -l -o.

I guess this is already fixed if I "reinstall" everything.

The WSL2 kernel is separate from the distros in Store. Its version is currently upgraded either by major Windows upgrades ([semi]annual), or manually. WSLg is also a separate download. But read on, there's a better option!

I just export the disk, unregister my distro and import the data [...]

Aha! I'm reminded of a fairly recent change I forgot to mention. There is a version of WSL in Store, which is decoupled from the semi-annual W10/annual W11 upgrade cadence. "Preview" does not mean it's beta, only indicates it's a Store version, not the one from the Windows image (like Windows Terminal Preview). Just a poor word choice. WSL2 will be moved to Store only and out of the main image to release more often. This newer version can mount VHDX virtual disks into WSL2 instances. You may break off Docker's storage to its own virtual disk, possibly on a different Windows drive, and mount it into /var/lib/docker. This isn't the only new feature. The first link is dated; the blog speaks of a “pre-release W11 version 22000,” but everything w.r.t. WSL2 is current.
devblogs.microsoft.com/commandline...
devblogs.microsoft.com/commandline...

Thread Thread
 
paulknulst profile image
Paul Knulst • Edited

Thanks for clarifiying. I never searched for Debian :-D I just thought that Windows only supports Ubuntu.

I know Debian (and many more Linux distros) but if I am not using Arch I prefer installing Ubuntu everywhere.

"Preview" does not mean it's beta

Moving of the vhdx image works in Ubuntu 22.04.1 LTS. I do not use preview version. But maybe I misunderstand your answer.

Collapse
 
paulknulst profile image
Paul Knulst • Edited

I just created a Docker CLI Cheatsheet that is very handy if not working with Docker Desktop anymore:

Image description

Download it here: paulsblog.dev/content/images/2022/...

Collapse
 
robertbernstein profile image
Robert Bernstein

Thanks for the great article! It had lots of useful information and suggestions.

Collapse
 
paulknulst profile image
Paul Knulst

Thanks for the feedback. I'm happy if I can help people with my tutorials :)