Skip to content
Go back

Access Docker socket via TCP

· Updated:
By SumGuy 5 min read
Access Docker socket via TCP

Find the config file

Edit config

Add the following configuration to the file:

{
"hosts": ["tcp://192.168.1.10:2375", "unix:///var/run/docker.sock"]
}

This tells Docker to listen on TCP port 2375 on IP (192.168.1.10) and on the Unix domain socket at /var/run/docker.sock. Replace 192.168.1.10 with your LAN or VPN IP.

The last line in that file must NOT have a comma after it, if there are more lines in there than the hosts’ line then add a comma to the end of all of them except the last one e.g.

{
"live-restore": true,
"max-concurrent-downloads": 5,
"max-concurrent-uploads": 5,
"hosts": ["tcp://192.168.1.10:2375", "unix:///var/run/docker.sock"]
}

DON’T MAKE THIS ACCESSIBLE TO ALL INTERNET BY USING 0.0.0.0 for the IP.

Test the configuration

Run the following command to test if the Docker socket is accessible via TCP:

docker -H tcp://192.168.1.10:2375 version

This will give a sample output like this :

❯ docker -H tcp://192.168.192.10:2375 version
Client: Docker Engine - Community
Version: 23.0.1
API version: 1.42
Go version: go1.19.5
Git commit: a5ee5b1
Built: Thu Feb 9 19:46:32 2023
OS/Arch: linux/arm64
Context: default
Server: Docker Engine - Community
Engine:
Version: 23.0.1
API version: 1.42 (minimum version 1.12)
Go version: go1.19.5
Git commit: bc3805a
Built: Thu Feb 9 19:46:32 2023
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.6.18
GitCommit: 2456e983eb9e37e47538f59ea18f2043c9a73640
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0

That’s it! You have now set up the Docker socket to be accessible via TCP. Keep in mind that exposing the Docker daemon on a network socket can be a security risk, so make sure to properly secure the socket and limit access to it, such as over VPN only or on lan only.

When it doesn’t work

The most common reason docker -H tcp://... fails right after you restart the daemon: systemd is overriding your config. By default, the Docker service unit passes -H fd:// to dockerd, and that flag wins over daemon.json. Result — Docker starts, but it’s only listening on the fd socket, not TCP. You’ll see something like:

Terminal window
$ docker -H tcp://192.168.1.10:2375 ps
error during connect: Get "http://192.168.1.10:2375/v1.24/containers/json": dial tcp 192.168.1.10:2375: connect: connection refused

Fix it by creating a systemd override that removes the conflicting flag:

Terminal window
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/override.conf > /dev/null <<’EOF’
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

The empty ExecStart= line clears whatever the stock unit defined. Now dockerd starts clean and picks up your daemon.json hosts list. Run docker -H tcp://192.168.1.10:2375 version again — it should work.

Persistent access with DOCKER_HOST

Typing -H tcp://192.168.1.10:2375 every single command gets old fast. Export DOCKER_HOST in your shell config and it becomes the default:

Terminal window
# in ~/.bashrc or ~/.zshrc on your local machine
export DOCKER_HOST=tcp://192.168.1.10:2375

After that, plain docker ps hits the remote daemon. Just remember to unset it when you need local Docker again — nothing quite like running docker rm -f and nuking containers on the wrong machine at 2 AM.

Firewall — don’t skip this

If you’re on a Linux host with ufw or firewalld, port 2375 won’t be open by default. Punch a hole, but scope it to your LAN range only:

Terminal window
# ufw example — allow only your LAN subnet
sudo ufw allow from 192.168.1.0/24 to any port 2375 proto tcp

If you’re on WireGuard or Tailscale, allow the VPN interface subnet instead. The goal is: your machines can reach it, random internet scanners cannot. Port 2375 is unauthenticated — if it’s reachable from the open internet you’ve basically handed out root to whoever finds it first.

Actually using it — Portainer, Dozzle, Yacht

The whole point of TCP access is usually to hook up a dashboard or remote compose client. Here are the typical connection strings:

ToolConnection string
Portainertcp://192.168.1.10:2375 in the “Docker API” environment setup
DozzleDOZZLE_REMOTE_HOST=tcp://192.168.1.10:2375|hostname env var
YachtDocker host: tcp://192.168.1.10:2375
Compose on remoteDOCKER_HOST=tcp://192.168.1.10:2375 docker compose up -d

Portainer’s the most common use case here — you want the single Portainer instance on your “main” box to manage containers on three or four other hosts. This is exactly how to wire that up without installing an agent on each one. Though honestly, Portainer’s agent approach is cleaner for that scenario. TCP socket is fine for quick connections and dashboards like Dozzle that just tail logs.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Dify: Visual Agent Workflows
Next Post
Advanced UFW Techniques: Enhancing Firewall Security

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts