By default, the Docker daemon socket (/var/run/docker.sock) is a Unix socket accessible only locally. When the Docker daemon needs to be accessible over the network — for remote Docker management, CI/CD pipelines connecting to a remote build host, or Docker Swarm cluster communication — TLS encryption must be configured to prevent man-in-the-middle attacks and unauthorised access. Docker’s TLS implementation uses mutual TLS (mTLS): both the server (daemon) and the client must present certificates signed by the same Certificate Authority. This means only clients with a certificate signed by your CA can connect, providing both encryption and strong authentication. This guide covers generating a CA and TLS certificates for Docker daemon TLS on RHEL 9 and configuring remote access.
Prerequisites
- Docker Engine installed on RHEL 9
- A stable IP or hostname for the Docker host
Step 1 — Create a Certificate Authority
mkdir -p /etc/docker/tls && cd /etc/docker/tls
# Generate CA private key and certificate
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -days 3650
-key ca-key.pem
-sha256
-out ca.pem
-subj "/CN=docker-ca"
Step 2 — Create the Server Certificate
# Replace 192.168.1.100 with your Docker host IP
SERVER_IP=192.168.1.100
SERVER_HOST=docker.example.com
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=${SERVER_HOST}" -sha256 -new
-key server-key.pem -out server.csr
# Include IP SAN — required for clients connecting by IP
echo "subjectAltName=DNS:${SERVER_HOST},IP:${SERVER_IP},IP:127.0.0.1" > extfile.cnf
echo "extendedKeyUsage=serverAuth" >> extfile.cnf
openssl x509 -req -days 3650 -sha256
-in server.csr -CA ca.pem -CAkey ca-key.pem
-CAcreateserial -out server-cert.pem
-extfile extfile.cnf
chmod 400 ca-key.pem server-key.pem
chmod 444 ca.pem server-cert.pem
Step 3 — Configure the Docker Daemon for TLS
# /etc/docker/daemon.json
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
"tlsverify": true,
"tlscacert": "/etc/docker/tls/ca.pem",
"tlscert": "/etc/docker/tls/server-cert.pem",
"tlskey": "/etc/docker/tls/server-key.pem"
}
# Fix systemd conflict (dockerd -H flag in service unit overrides daemon.json hosts)
mkdir -p /etc/systemd/system/docker.service.d/
cat > /etc/systemd/system/docker.service.d/override.conf <<EOF
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
EOF
systemctl daemon-reload
systemctl restart docker
# Allow TLS port through firewall
firewall-cmd --permanent --add-port=2376/tcp
firewall-cmd --reload
Step 4 — Generate Client Certificates
openssl genrsa -out client-key.pem 4096
openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr
echo "extendedKeyUsage=clientAuth" > extfile-client.cnf
openssl x509 -req -days 3650 -sha256
-in client.csr -CA ca.pem -CAkey ca-key.pem
-CAcreateserial -out client-cert.pem
-extfile extfile-client.cnf
# Copy ca.pem, client-cert.pem, and client-key.pem to the client machine
Step 5 — Connect from a Remote Client
# On the remote client (copy certs to ~/.docker/)
mkdir -p ~/.docker
cp ca.pem client-cert.pem client-key.pem ~/.docker/
# Connect to the remote Docker daemon
docker --tlsverify
--tlscacert=~/.docker/ca.pem
--tlscert=~/.docker/client-cert.pem
--tlskey=~/.docker/client-key.pem
-H tcp://192.168.1.100:2376 info
# Set environment variables to avoid specifying flags each time
export DOCKER_HOST=tcp://192.168.1.100:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker
Conclusion
Docker daemon TLS on RHEL 9 provides both encryption and mutual authentication for remote Docker access. The Subject Alternative Name (SAN) extension in the server certificate is mandatory — modern TLS clients reject certificates that do not include SAN entries for the hostname or IP being connected to. Never expose the Docker daemon on TCP without TLS: an unauthenticated Docker TCP port provides full root access to the host, as an attacker can mount the host filesystem via a privileged container.
Next steps: How to Set Up a Private Docker Registry on RHEL 9, How to Use Docker Secrets Securely on RHEL 9, and How to Install Kubernetes on RHEL 9.