This error occurs when Docker is configured to connect via TCP on port 2375, but the daemon is not listening on that port. This commonly affects WSL, CI/CD pipelines, and Docker-in-Docker setups.
When Docker commands fail with "Cannot connect to the Docker daemon at tcp://localhost:2375", the Docker CLI is attempting to communicate with the Docker daemon over TCP port 2375 instead of the default Unix socket. This TCP connection mode is typically used in specific scenarios: - **WSL (Windows Subsystem for Linux)**: To connect from WSL to Docker Desktop running on Windows - **CI/CD pipelines**: In GitLab CI, Jenkins, or other CI systems using Docker-in-Docker (dind) - **Remote Docker access**: When connecting to a Docker daemon on another machine - **Development tools**: Some IDEs and development tools require TCP access to Docker The error indicates either that the Docker daemon is not running at all, or that it is not configured to listen on the TCP port. By default, Docker listens only on a Unix socket (`/var/run/docker.sock`) for security reasons, as exposing the daemon over TCP without TLS allows anyone with network access to control Docker.
First, verify if DOCKER_HOST is explicitly set:
echo $DOCKER_HOSTIf this returns tcp://localhost:2375 or similar, that's why Docker is trying to connect via TCP.
To unset it temporarily:
unset DOCKER_HOST
docker versionIf Docker works after unsetting, the fix is to remove DOCKER_HOST from your shell configuration files (~/.bashrc, ~/.zshrc, ~/.profile).
If you're using WSL2 with Docker Desktop, you should NOT use the TCP connection method. Docker Desktop provides native WSL2 integration:
1. Open Docker Desktop
2. Go to Settings (gear icon)
3. Navigate to Resources > WSL Integration
4. Enable integration for your WSL distribution
5. Click Apply & Restart
Then in your WSL terminal:
# Remove DOCKER_HOST from your shell config
sed -i '/DOCKER_HOST/d' ~/.bashrc
sed -i '/DOCKER_HOST/d' ~/.zshrc
# Reload your shell
source ~/.bashrc
# Verify Docker works
docker versionWith WSL2 integration, Docker commands work natively without any environment variables.
If you specifically need TCP access (WSL1, or accessing Docker from another application):
1. Open Docker Desktop
2. Go to Settings (gear icon)
3. Check "Expose daemon on tcp://localhost:2375 without TLS"
4. Click Apply & Restart
Warning: This exposes Docker without encryption or authentication. Only use this on trusted networks, and never on publicly accessible machines.
Then verify the connection:
export DOCKER_HOST=tcp://localhost:2375
docker versionOn Linux, you need to configure the Docker daemon to listen on TCP:
Method 1: Using systemd override (recommended)
Create a systemd drop-in file:
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/override.confAdd the following content:
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://127.0.0.1:2375Then reload and restart Docker:
sudo systemctl daemon-reload
sudo systemctl restart dockerMethod 2: Using daemon.json
Edit /etc/docker/daemon.json:
{
"hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
}Then restart Docker:
sudo systemctl restart dockerSecurity Note: Binding to 127.0.0.1 restricts access to localhost only. Never bind to 0.0.0.0 without TLS and authentication.
In GitLab CI with Docker-in-Docker (dind), the Docker daemon runs as a separate service, not on localhost:
# .gitlab-ci.yml
image: docker:latest
services:
- docker:dind
variables:
# Use 'docker' hostname, not 'localhost'
DOCKER_HOST: tcp://docker:2375
# For Docker 19.03+ with TLS:
# DOCKER_HOST: tcp://docker:2376
# DOCKER_TLS_CERTDIR: "/certs"
build:
script:
- docker version
- docker build -t myimage .Important: The hostname docker refers to the dind service container. Using localhost or 127.0.0.1 will fail because the daemon is in a different container.
Different CI/CD systems have different configurations for Docker-in-Docker:
Jenkins:
pipeline {
agent {
docker {
image 'docker:dind'
args '--privileged'
}
}
environment {
DOCKER_HOST = 'tcp://localhost:2375'
}
}GitHub Actions:
jobs:
build:
runs-on: ubuntu-latest
services:
docker:
image: docker:dind
options: --privileged
steps:
- name: Build
env:
DOCKER_HOST: tcp://docker:2375
run: docker build .Bitbucket Pipelines:
Enable Docker in your pipeline configuration and use the default socket, or configure TCP access on the runner.
To debug further, check if Docker is running and listening on the expected port:
Check if Docker daemon is running:
# On Linux
sudo systemctl status docker
# On Windows (PowerShell)
Get-Service *docker*Check if port 2375 is listening:
# On Linux
ss -tlnp | grep 2375
# or
netstat -tlnp | grep 2375
# On Windows (PowerShell)
netstat -an | findstr 2375Test TCP connection:
curl http://localhost:2375/version
# or
nc -zv localhost 2375If nothing is listening on port 2375, the daemon needs to be configured to listen on TCP (see previous steps).
If Docker fails to bind to port 2375, another application might be using it:
Find what's using port 2375:
# On Linux
sudo lsof -i :2375
# or
sudo ss -tlnp | grep 2375
# On Windows (PowerShell as Administrator)
netstat -ano | findstr 2375
# Then find the process
Get-Process -Id <PID>Common conflicts:
- Another Docker daemon instance
- Docker Desktop already running
- Kubernetes or minikube
- Development tools that proxy Docker
Stop the conflicting application or configure Docker to use a different port.
Security considerations for TCP access:
Exposing Docker over TCP without TLS (port 2375) is a significant security risk. Anyone who can reach the port can:
- Run arbitrary containers with full root access to the host
- Access all images, containers, and volumes
- Modify Docker networks and potentially pivot to other systems
For production or untrusted networks, always use TLS (port 2376):
1. Generate TLS certificates:
# Create CA and certificates
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
# ... (full certificate generation process)2. Configure Docker daemon:
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
"tls": true,
"tlscacert": "/etc/docker/ca.pem",
"tlscert": "/etc/docker/server-cert.pem",
"tlskey": "/etc/docker/server-key.pem",
"tlsverify": true
}3. Configure Docker client:
export DOCKER_HOST=tcp://hostname:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.dockerWSL1 vs WSL2:
- WSL1 required TCP connection to Docker Desktop
- WSL2 uses native integration (no TCP needed)
- If you upgraded from WSL1 to WSL2, remove old DOCKER_HOST settings
Docker context for managing connections:
# Create a context for TCP connection
docker context create tcp-docker --docker "host=tcp://localhost:2375"
# Switch to it
docker context use tcp-docker
# Switch back to default
docker context use defaultimage operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub