Configure Docker Daemon for Remote Connections

|
Last Updated:
|
|

Is it possible to connect Docker daemon running on remote host from local Docker client? Yes, this tutorial will take you through how to configure Docker daemon for remote connections. Docker daemon listens on Unix socket on a localhost by default. It can as well be configured to listen on an IP address and port to allow remote clients to connect to it.

Configure Docker Daemon for Remote Connections

Configuring Docker Daemon for Remote Connections

As already mentioned, Docker daemon can listens on non-networked unix socket by default. It can however be configured to listen on both an IP and port as well as on usual unix socket.

There are two ways in which you can configure Docker daemon to allow remote connections (You can only use one method and not both at the same time on the same system).

  1. Via Docker daemon Systemd service unit file
  2. via Docker daemon.json file

Use Systemd Service Unit File to enable Docker Daemon Remote Connections

For systems that uses systemd and have Docker engine installed, then you can edit the Docker daemon service unit file, docker.service, and configure it to listen on an IP and port.

Create a systemd drop-in directory for the docker service:

sudo mkdir -p /etc/systemd/system/docker.service.d

Configure the overide file to look like;

sudo tee /etc/systemd/system/docker.service.d/override.conf << 'EOL' 
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://192.168.59.48:2375
EOL

Port 2375/TCP is the default port used for the Docker daemon to listen on for API requests.

Above configures Docker daemon to listen on specific IP address only. You can use 0.0.0.0 to listen on all interfaces.

You might be wondering why an extra ExecStart line without a value? Well, ExecStart= with no value is typically used to clear any previously defined ExecStart commands from the original service file. It ensures that the original ExecStart command is cleared before adding your new command with ExecStart=/new/value.

Reload the systemctl configuration.

sudo systemctl daemon-reload

Restart Docker.

sudo systemctl restart docker

Verify that it is now listening on both Unix socket and IP/port;

ss -altnp | grep :2375
LISTEN 0      4096   192.168.59.48:2375      0.0.0.0:*    users:(("dockerd",pid=3344,fd=3))

Enable Docker Remote Connections via daemon.json file

daemon.json is a configuration file for the Docker daemon used to set various options and settings for the Docker daemon, such as network settings, storage drivers, logging options, and more.

You can edit this file, if it is already existing and configure it as follows to enable Docker daemon for remote connections;

sudo vim /etc/docker/daemon.json
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://192.168.59.48:2375"]
}

If the file already exists, add that line and ensure that the file remains a valid json file.

Save and exit the file.

Restart Docker daemon;

sudo systemctl restart docker

If docker service fails with the error;

unable to configure the Docker daemon with file /etc/docker/daemon.json: the following directives are specified both as a flag and in the configuration file: hosts: (from flag: [fd://], from file: [unix:///var/run/docker.sock tcp://192.168.59.48:2375])

Then solve by removing the -H fd:// option from the systemd unit file it as follows;

[[ -d /etc/systemd/system/docker.service.d ]] || sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/override.conf << 'EOL' 
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock
EOL

Restart Docker again;

sudo systemctl restart docker

Control Docker Daemon Remote Access on Firewall

Allowing remote access to Docker daemon is a security risk. Ensure that you implement firewall rules to allow access from specific systems only.

For example, the command below can be used to allow access to Docker daemon from specific host;

sudo ufw allow from 192.168.59.46 to any port 2375 proto tcp comment "Allow access from johndoes system"

If using iptables;

sudo iptables -A INPUT -p tcp --dport 2375 -s 192.168.59.100/32 -m comment --comment "Allow from johndoes system" -j ACCEPT
sudo cp /etc/iptables/rules.v4{,.bak}
iptables-save > /etc/iptables/rules.v4

Configure Secured Access to Remote Docker Daemon

There are also two methods in which you can configure secured access to remote Docker deamon;

  1. Access Docker Daemon via SSH
  2. Connect to Docker Daemon using via TLS (HTTPS)

Access Docker Daemon via SSH

To begin with, on the Docker host, where you have configured Docker daemon for remote access, create a user and add the user to Docker group. The name can be anything!

sudo useradd -m -G docker -s /bin/bash kifarunix

Set the user password;

sudo passwd kifarunix

If the user already exists, add it to Docker group;

sudo usermod -aG docker kifarunix

On the client host that you want to use to connect to remote Docker daemon, generate SSH keys from your user account;

ssh-keygen

Next, update the remote Docker daemon DNS details on your hosts file if there is no local DNS;

sudo tee -a "192.168.59.48 docker01.kifarunix.com docker01" >> /etc/hosts

Copy the SSH keys into the Docker server, replace connection details appropriately;

ssh-copy-id kifarunix@docker01

You can now access remote Docker daemon as follows;

docker -H ssh://username@remote-docker-hostname <docker command options>

For example, to get info about remote Docker daemon;

docker -H ssh://kifarunix@docker01 info

You can also update the DOCKER_HOST environment variable with SSH connection command;

export DOCKER_HOST=ssh://username@remote-docker-hostname

e.g;

export DOCKER_HOST=ssh://kifarunix@docker01

With this done, then you can ran your docker commands against the remote host as you would when logged in to that server;

docker ps

If you are running Docker engine on the client node you are using to access remote Docker daemon, you can create Docker contexts that enables you to switch between the local and remote Docker daemon.

By default, the local Docker context that defines the local Docker daemon socket, unix:///var/run/docker.sock, is created;

docker context ls
NAME        DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default *   Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm

You can create another Docker context to define remote Docker daemon endpoint;

docker context create \
--docker host=ssh://docker-user@hostname \
--description="Description" \
context-name

E.g to create a Docker context for our remote Docker daemon;

docker context create \
--docker host=ssh://kifarunix@docker01 \
--description="Remote DOCKER_HOST docker01 configuration" \
docker01

You can list contexts again;

docker context ls
NAME        DESCRIPTION                                 DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default *   Current DOCKER_HOST based configuration     unix:///var/run/docker.sock                         swarm
docker01    Remote DOCKER_HOST docker01 configuration   ssh://kifarunix@docker01

To connect to a remote Docker daemon using Docker contexts, simply use the specific Docker context. e.g;

docker context use docker01

If you list contexts again, you will see that current context is the remote context;

docker context ls
NAME         DESCRIPTION                                 DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default      Current DOCKER_HOST based configuration     unix:///var/run/docker.sock                         swarm
docker01 *   Remote DOCKER_HOST docker01 configuration   ssh://kifarunix@docker01

You can then run Docker commands against remote Docker host as usual;

e.g

docker ps

This list Docker containers running on the remote Docker node;

CONTAINER ID   IMAGE                      COMMAND                  CREATED       STATUS                 PORTS                                       NAMES
950a8a3f3bb6   grafana/grafana-oss        "/run.sh"                2 weeks ago   Up 2 hours             0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   grafana
ce3eb465e820   prom/prometheus            "/bin/prometheus --c…"   2 weeks ago   Up 2 hours             0.0.0.0:9090->9090/tcp, :::9090->9090/tcp   prometheus
567d549c4768   gcr.io/cadvisor/cadvisor   "/usr/bin/cadvisor -…"   2 weeks ago   Up 2 hours (healthy)   0.0.0.0:9080->8080/tcp, :::9080->8080/tcp   cadvisor
8d2a1aac1384   mariadb                    "docker-entrypoint.s…"   4 weeks ago   Up 2 hours             3306/tcp                                    wp-mariadb
b46dce1fc33c   amir20/dozzle:latest       "/dozzle"                6 weeks ago   Up 3 hours             0.0.0.0:8888->8080/tcp, :::8888->8080/tcp   dozzle
1421e6e27733   nagios-core:4.4.9          "/start.sh"              6 weeks ago   Up 2 hours             0.0.0.0:80->80/tcp, :::80->80/tcp           nagios-core-4.4.9

And that is on how you can use SSH to connect to remote Docker daemon.

Connect to Docker Daemon using via TLS (HTTPS)

Docker over TLS should run on TCP port 2376.

Thus, similarly, you can enable HTTPS connection to your remote Docker daemon. To be able to use HTTPS connection to remote Docker container, you need SSL/TLS certificates.

To make this process easy and cost effective, you can setup your own CA server that enables you to generate and sign your own SSL/TLS certificates;

How to Setup a Local CA Server on Ubuntu

Thus, on your CA server, generate SSL/TLS certificates to be installed on the remote Docker server node and clients connecting to it to develop trust among them.

Generate Docker SSL/TLS certificates and keys (you can follow the guide above to generate and sign your own ssl certificates);

Put the certificates and keys on a single directory for easy access.

For example, we have the following;

ls /etc/ssl/docker/
cacert.pem
docker01.crt
docker01.key

You will need to copy these same files into Docker client.

Configure Daemon for Remote SSL/TLS connection;

For this, you can use either daemon.json file or systemd unit file for Docker daemon.

To use daemon.json, update it such that it may look like in below, ensuring that the file remains a valid JSON file.

sudo vim /etc/docker/daemon.json
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://192.168.59.48:2376"],
  "tlsverify": true,
  "tlscacert": "/etc/ssl/docker/cacert.pem",
  "tlscert": "/etc/ssl/docker/docker01.crt",
  "tlskey": "/etc/ssl/docker/docker01.key"
}

Restart Docker daemon;

sudo systemctl restart docker

Check the port;

ss -altnp | grep 2376

Also check logs if need be;

journalctl -xeu docker.service

Open port 2376/tcp on firewall;

iptables -A INPUT -p tcp --dport 2376 -s 192.168.59.100/32 -m comment --comment "Allow from johndoes system" -j ACCEPT

To configure Docker daemon for SSL/TLS connection using systemd unit file;


sudo tee /etc/systemd/system/docker.service.d/override.conf << 'EOL' 
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://192.168.59.48:2376 \
  --tlsverify --tlscacert=/etc/ssl/docker/cacert.pem \
  --tlscert=/etc/ssl/docker/docker01.crt \
  --tlskey=/etc/ssl/docker/docker01.key
EOL

Reload the systemctl configuration.

sudo systemctl daemon-reload

Restart Docker.

sudo systemctl restart docker

Next, copy the CA, CRT and KEY files into the client into your users Docker directory, ~/.docker and rename them as ca.pem, key.pem, cert.pem.

On Docker Client, we have already copied the files;

ls -1 ~/.docker/
ca.pem
config.json
contexts
cert.pem
key.pem

You can now connect to remote Docker node using the command;

export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1

e.g

export DOCKER_HOST=tcp://docker01.kifarunix.com:2376 DOCKER_TLS_VERIFY=1

We used FQDN since we generated a wildcard SSL/TLS certificate.

You can now access remote Docker host as usual;

docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED       STATUS          PORTS                                       NAMES
950a8a3f3bb6   grafana/grafana-oss    "/run.sh"                2 weeks ago   Up 16 minutes   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   grafana
ce3eb465e820   prom/prometheus        "/bin/prometheus --c…"   2 weeks ago   Up 16 minutes   0.0.0.0:9090->9090/tcp, :::9090->9090/tcp   prometheus
8d2a1aac1384   mariadb                "docker-entrypoint.s…"   4 weeks ago   Up 16 minutes   3306/tcp                                    wp-mariadb
b46dce1fc33c   amir20/dozzle:latest   "/dozzle"                6 weeks ago   Up 16 minutes   0.0.0.0:8888->8080/tcp, :::8888->8080/tcp   dozzle
1421e6e27733   nagios-core:4.4.9      "/start.sh"              6 weeks ago   Up 16 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp           nagios-core-4.4.9

And that is all on how to configure Docker daemon for remote connections.

Reference

Remote access for Docker daemon

Other Tutorials

How to Install Docker Desktop on Kali Linux

How to Deploy an Application in a Docker Swarm Cluster

SUPPORT US VIA A VIRTUAL CUP OF COFFEE

We're passionate about sharing our knowledge and experiences with you through our blog. If you appreciate our efforts, consider buying us a virtual coffee. Your support keeps us motivated and enables us to continually improve, ensuring that we can provide you with the best content possible. Thank you for being a coffee-fueled champion of our work!

Photo of author
Kifarunix
Linux Certified Engineer, with a passion for open-source technology and a strong understanding of Linux systems. With experience in system administration, troubleshooting, and automation, I am skilled in maintaining and optimizing Linux infrastructure.

Leave a Comment