Skip to content

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

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"]
}

If your Docker service is started by systemd and the unit file includes -H flags, you may need to override the service file to avoid conflicts with the hosts setting in daemon.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

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.