SSH Connections

aiodocker supports connecting to remote Docker hosts over SSH using the ssh:// URL scheme. This feature requires the asyncssh library and follows the same security principles as docker-py.

The SSH connector uses docker system dial-stdio to communicate with the remote Docker daemon, which automatically discovers and uses the correct socket path on the remote host. This works seamlessly with standard Docker installations, rootless Docker, and custom socket configurations without requiring manual socket path specification.

Installation

Install aiodocker with SSH support:

pip install aiodocker[ssh]

Basic Usage

Connect to a remote Docker host using an SSH URL:

import asyncio
import aiodocker

async def main():
    # Connect to Docker over SSH
    async with aiodocker.Docker(url="ssh://user@remote-host:22") as docker:
        # Use Docker API normally
        version = await docker.version()
        print(f"Docker version: {version['Version']}")

        # List containers
        containers = await docker.containers.list()
        for container in containers:
            print(f"Container: {container['Names'][0]}")

if __name__ == "__main__":
    asyncio.run(main())

URL Format

SSH URLs follow this format:

ssh://[user[:password]@]host[:port]

Examples:

  • ssh://ubuntu@host:22 - Connect to host on port 22

  • ssh://ubuntu@host - Connect using default SSH port (22)

  • ssh://dockeruser@production.example.com:2222 - Custom port

Note on Socket Paths:

Unlike traditional SSH port forwarding approaches, aiodocker uses docker system dial-stdio which automatically discovers the correct Docker socket on the remote host. Socket paths in URLs (e.g., ssh://user@host///var/run/docker.sock) are accepted for backward compatibility but are ignored.

This automatic discovery means the connector works correctly with:

  • Standard Docker installations (/var/run/docker.sock)

  • Rootless Docker (/run/user/1000/docker.sock)

  • Custom socket paths configured in the remote Docker daemon

  • Docker contexts on the remote host

Authentication

Password Authentication (Discouraged)

Passwords can be included in URLs but this is not recommended for security reasons:

# Warning: Password will be stored in memory and may appear in logs
async with aiodocker.Docker(url="ssh://ubuntu:password@host:22") as docker:
    containers = await docker.containers.list()

Host Key Verification

By default, aiodocker enforces strict host key verification for security. The remote host must be present in ~/.ssh/known_hosts.

Adding Host Keys

Add the remote host to your known hosts file:

# Method 1: Connect manually to add host key
ssh ubuntu@remote-host

# Method 2: Add host key directly
ssh-keyscan -H remote-host >> ~/.ssh/known_hosts

# Method 3: Copy from another trusted machine
scp trusted-machine:~/.ssh/known_hosts ~/.ssh/known_hosts

Relaxing Host Key Verification

For testing environments only, you can disable strict host key checking:

from aiodocker.ssh import SSHConnector

# WARNING: Only for testing - vulnerable to man-in-the-middle attacks
connector = SSHConnector(
    "ssh://ubuntu@test-host:22",
    strict_host_keys=False
)
async with aiodocker.Docker(connector=connector) as docker:
    containers = await docker.containers.list()

SSH Configuration

aiodocker automatically reads SSH configuration from ~/.ssh/config when the paramiko library is available.

Example SSH config:

Host docker-prod
    HostName production.example.com
    User dockeruser
    Port 2222
    IdentityFile ~/.ssh/docker_prod_key
    UserKnownHostsFile ~/.ssh/known_hosts_prod

Host docker-staging
    HostName staging.example.com
    User ubuntu
    Port 22
    IdentityFile ~/.ssh/docker_staging_key

Usage with SSH config:

# Automatically uses settings from ~/.ssh/config
async with aiodocker.Docker(url="ssh://docker-prod") as docker:
    containers = await docker.containers.list()

Advanced Configuration

Custom SSH Options

Pass additional SSH options directly to the underlying asyncssh connection:

from aiodocker.ssh import SSHConnector

connector = SSHConnector(
    "ssh://ubuntu@host:22",
    # Custom SSH options
    compression=True,
    keepalive_interval=30,
    known_hosts="/custom/path/known_hosts"
)
async with aiodocker.Docker(connector=connector) as docker:
    containers = await docker.containers.list()

Connection Reuse

For better performance, reuse the same connector across multiple Docker instances:

from aiodocker.ssh import SSHConnector

# Create connector once
connector = SSHConnector("ssh://ubuntu@host:22")

# Reuse across multiple Docker instances
async with aiodocker.Docker(connector=connector) as docker1:
    containers = await docker1.containers.list()

async with aiodocker.Docker(connector=connector) as docker2:
    images = await docker2.images.list()

# Clean up when done
await connector.close()

Security Considerations

The SSH implementation follows security best practices:

Environment Sanitization

Potentially dangerous environment variables are automatically removed from SSH connections:

  • LD_LIBRARY_PATH

  • SSL_CERT_FILE

  • SSL_CERT_DIR

  • PYTHONPATH

Credential Protection

  • Passwords are cleared from memory after successful connection

  • Error messages sanitize credential information to prevent leakage

  • Log messages are filtered to avoid password exposure

Secure Temporary Files

Local socket files are created in secure temporary directories with restricted permissions (mode 0700), ensuring only the current user can access them.

Troubleshooting

Common Issues

“Host key verification failed”

Add the host to your known hosts file:

ssh-keyscan -H hostname >> ~/.ssh/known_hosts

“Permission denied (publickey)”

Ensure your SSH key is properly configured:

ssh-add ~/.ssh/your_key
ssh ubuntu@hostname  # Test SSH connection manually

“Connection refused”

Verify the SSH service is running and accessible:

telnet hostname 22

Debugging

Enable debug logging to troubleshoot connection issues:

import logging
logging.basicConfig(level=logging.DEBUG)

async with aiodocker.Docker(url="ssh://ubuntu@host:22") as docker:
    containers = await docker.containers.list()

Requirements

  • asyncssh >= 2.14.0 (installed automatically with aiodocker[ssh])

  • SSH access to the remote Docker host

  • Docker CLI (docker command) available on the remote host (required for docker system dial-stdio)

  • Docker daemon running and accessible on the remote host

Reference

SSHConnector

class aiodocker.ssh.SSHConnector(ssh_url: str, strict_host_keys: bool = True, **kwargs: Any)[source]

SSH tunnel connector that forwards Docker socket connections over SSH.

async close() None[source]

Close SSH connection and clean up resources with proper error handling.

async connect(req: ClientRequest, traces: Any, timeout: ClientTimeout) Connection[source]

Connect through SSH tunnel.