Last updated: 2026-02-11
Docker TLS/SSL Configuration Guide
This guide provides recommended TLS/SSL settings for securing the Docker daemon API with TLS. By default, the Docker daemon listens on a Unix socket. When exposing it over a network (TCP), TLS with client certificate authentication is essential to prevent unauthorized access -- anyone with network access to an unprotected Docker daemon has full root access to the host.
Prerequisites
- Docker Engine 20.10 or later
- OpenSSL 1.1.1 or later
Certificate Generation
Docker TLS requires a CA, server certificate, and client certificate. The server certificate authenticates the daemon, and the client certificate authenticates the user.
Create a CA
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem \
-subj "/CN=Docker CA"
Create the Server Certificate
Create a server key and certificate signing request:
openssl genrsa -out server-key.pem 4096
openssl req -new -key server-key.pem -sha256 -out server.csr \
-subj "/CN=docker.example.com"
Create a SAN extension file to include all hostnames and IPs the daemon will be accessed by:
echo "subjectAltName = DNS:docker.example.com,IP:10.0.0.1,IP:127.0.0.1" > extfile-server.cnf
echo "extendedKeyUsage = serverAuth" >> extfile-server.cnf
Sign the server certificate:
openssl x509 -req -days 365 -sha256 -in server.csr \
-CA ca.pem -CAkey ca-key.pem -CAcreateserial \
-out server-cert.pem -extfile extfile-server.cnf
Create the Client Certificate
openssl genrsa -out client-key.pem 4096
openssl req -new -key client-key.pem -sha256 -out client.csr \
-subj "/CN=client"
echo "extendedKeyUsage = clientAuth" > extfile-client.cnf
openssl x509 -req -days 365 -sha256 -in client.csr \
-CA ca.pem -CAkey ca-key.pem -CAcreateserial \
-out client-cert.pem -extfile extfile-client.cnf
Set Permissions
chmod 600 ca-key.pem server-key.pem client-key.pem
chmod 644 ca.pem server-cert.pem client-cert.pem
Install Certificates
Copy server certificates to the Docker host:
mkdir -p /etc/docker/ssl
cp ca.pem server-cert.pem server-key.pem /etc/docker/ssl/
Copy client certificates to each machine that needs Docker API access:
mkdir -p ~/.docker
cp ca.pem client-cert.pem client-key.pem ~/.docker/
Daemon Configuration
Configure the Docker daemon to require TLS for all TCP connections. Edit /etc/docker/daemon.json:
{
"tls": true,
"tlsverify": true,
"tlscacert": "/etc/docker/ssl/ca.pem",
"tlscert": "/etc/docker/ssl/server-cert.pem",
"tlskey": "/etc/docker/ssl/server-key.pem",
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}
- tls: true enables TLS encryption.
- tlsverify: true requires clients to present a valid certificate signed by the CA. This is critical -- without
tlsverify, any client can connect. - hosts lists the interfaces to listen on. Port 2376 is the standard TLS-secured Docker port (2375 is the unencrypted port and should never be exposed).
If your Docker service is started by systemd and the unit file includes
-Hflags, you may need to override the service file to avoid conflicts with thehostssetting indaemon.json. Create an override:
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
Client Configuration
Environment Variables
Set environment variables to tell the Docker CLI to use TLS:
export DOCKER_HOST=tcp://docker.example.com:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker
Command-Line Flags
Or pass TLS options directly:
docker --tlsverify \
--tlscacert=~/.docker/ca.pem \
--tlscert=~/.docker/client-cert.pem \
--tlskey=~/.docker/client-key.pem \
-H tcp://docker.example.com:2376 info
Docker Context
Create a named context for the TLS-secured host:
docker context create secure-host \
--docker "host=tcp://docker.example.com:2376,ca=~/.docker/ca.pem,cert=~/.docker/client-cert.pem,key=~/.docker/client-key.pem"
docker context use secure-host
Docker Compose
Docker Compose uses the same environment variables:
export DOCKER_HOST=tcp://docker.example.com:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker
docker compose up -d
Security Considerations
- Never expose port 2375 (unencrypted Docker API) to any network. An unprotected Docker socket grants root access to the host.
- Always use
tlsverify, not justtls. Thetlsflag alone encrypts traffic but does not authenticate clients. - Protect the CA key (
ca-key.pem). Anyone with the CA key can generate client certificates and access the daemon. - Use short-lived certificates and rotate them regularly.
- Prefer the Unix socket for local access. Only expose TCP when remote access is required.
Verification
Restart Docker:
systemctl restart docker
Test the TLS connection:
docker --tlsverify -H tcp://docker.example.com:2376 info
Verify with OpenSSL:
openssl s_client -connect docker.example.com:2376 -cert ~/.docker/client-cert.pem -key ~/.docker/client-key.pem -CAfile ~/.docker/ca.pem
Verify a connection without a client certificate is rejected:
curl https://docker.example.com:2376/info --cacert ~/.docker/ca.pem
This should fail with a TLS handshake error, confirming client certificate verification is enforced.