I had an old laptop where I installed Docker Desktop. While I mainly used the command line, I still experienced all the downsides that come with it, it made my laptop super slow and added unnecessary overhead. Today, when I wanted to install Docker on a new Windows machine, those past memories hit me. So, I decided to install just the CLI without the slow UI. I’ll share my process with you in this tutorial.
So, without further ado, let’s learn how to install and use Docker on Windows without Docker Desktop!
Prerequisites
- WSL2 (If you don’t have it installed, open PowerShell as Administrator and run
wsl --install
) - Administrator access on your Windows machine
Step 1: Install Docker in WSL
First, we need to install Docker on WSL Linux distribution. Open your WSL terminal and follow the instructions here, assuming you’re using Ubuntu:
Step 2: Install Docker CLI on Windows
Since there’s no official Windows release for the Docker CLI alone, we’ll need to build it ourselves or use a pre-built binary. Here are two options:
Option A: Build it yourself (Advanced)
- Get a temporary VPS with Docker installed.
- Clone the Docker CLI repository:
git clone https://github.com/docker/cli.git
- Build it using:
docker buildx bake --set binary.platform=windows/amd64
- Rename the resulting
docker-windows-amd64.exe
todocker.exe
Option B: Download pre-built binary (Easier)
After obtaining the docker.exe
file, create a new folder at C:\Users\YourUsername\Docker
and place the file there. Then, add this folder to your Windows PATH environment variable.
Step 3: Configure Docker Daemon in WSL
Now, we need to configure the Docker daemon in WSL to listen on a TCP port. In your WSL terminal:
sudo mkdir -p /etc/docker
sudo nano /etc/docker/daemon.json
Add the following content to the file:
{
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
Step 4: Create a Systemd Override for Docker
We need to tell systemd to use our custom configuration:
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/override.conf
Add the following content:
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --config-file /etc/docker/daemon.json
Step 5: Restart Docker in WSL
Apply the changes by reloading systemd and restarting Docker:
sudo systemctl daemon-reload
sudo service docker restart
Step 6: Configure Docker CLI on Windows
Create or edit the file %USERPROFILE%\.docker\config.json
(typically C:\Users\YourUsername\.docker\config.json
) and add:
{
"host": "tcp://localhost:2375"
}
Step 7: Set Windows Environment Variable
Open PowerShell as Administrator and run:
[Environment]::SetEnvironmentVariable("DOCKER_HOST", "tcp://localhost:2375", "User")
Step 8: Configure Windows Firewall
We need to allow the connection through the Windows Firewall. In PowerShell as Administrator, run:
New-NetFirewallRule -DisplayName "WSL 2 Docker" -Direction Inbound -LocalPort 2375 -Action Allow -Protocol TCP
New-NetFirewallRule -DisplayName "WSL 2 Docker Outbound" -Direction Outbound -LocalPort 2375 -Action Allow -Protocol TCP
Step 9: Restart and Test
Restart your WSL instance and open a new PowerShell window to ensure all changes are reflected. Then, test your Docker installation:
docker version
docker run hello-world
If everything is set up correctly, you should see the Docker version information and the “Hello from Docker!” message.
Installing Docker Compose (Optional)
Now that Docker is running in WSL, let’s add Docker Compose for managing multi-container applications. The modern Docker installation includes Compose as a plugin, which uses the command docker compose
(with a space) rather than the older docker-compose
format.
First, install the Docker Compose plugin in your WSL environment:
sudo apt update
sudo apt install docker-compose-plugin
Verify the installation:
docker compose version
This should display something like Docker Compose version v2.39.1
. For most modern projects, this is all you need. You can now use docker compose up
, docker compose down
, and other commands with the space syntax.
Creating Compatibility for Legacy Tools (Optional)
Recently, I encountered a package that specifically required docker-compose
(with hyphen) as a dependency. Some older scripts, tools, and documentation still expect this format. If you run into similar compatibility requirements, here’s how to create a wrapper that bridges both formats.
In WSL:
Create a wrapper script that translates the hyphenated command to the modern format:
- Open your WSL terminal
- Create the wrapper script:
sudo nano /usr/local/bin/docker-compose
- Add this content:
#!/bin/sh docker compose --compatibility "$@"
- Save and exit (
Ctrl+X
, thenY
, thenEnter
) - Make it executable:
sudo chmod +x /usr/local/bin/docker-compose
The --compatibility
flag helps when working with older compose file formats by converting certain version 1 behaviors to work with version 2.
In Windows:
If you also need the hyphenated command to work from Windows Command Prompt or PowerShell:
- Create a batch file called
docker-compose.bat
in a directory that’s in your PATH (or createC:\bin\
and add it to PATH) - Add this content:
@echo off wsl docker compose --compatibility %*
- If you created a new directory, add it to your Windows PATH through System Properties → Environment Variables
- Restart your terminal
Testing Docker Compose
Test your setup with a simple compose file. Create a file named docker-compose.yml
:
version: '3'
services:
hello:
image: hello-world
Then run:
# Using the modern syntax
docker compose up
# Or if you created the compatibility wrapper
docker-compose up
Both commands should pull and run the hello-world image successfully.
Note: Unless you have specific tools requiring the hyphenated format, stick with docker compose
(with space) as it’s the current standard. The compatibility wrapper is just a convenience for edge cases where legacy support is needed.
And there you have it! You’ve successfully installed Docker on Windows without Docker Desktop. This setup gives you a lightweight Docker environment that doesn’t slow down your system like Docker Desktop can.