Search code examples
macosssldockerdocker-machinedockerpy

Connecting to Docker-Machine via docker-py on OSX


Context

I am trying to use docker-py to connect to docker-machine on OSX.

I can't simply use the standard Client(base_url='unix://var/run/docker.sock') since docker is running on a docker-machine Virtual Machine, not my local OS.

Instead, I am trying to connect securely to the VM using docker.tls:

from docker import Client
import docker.tls as tls
from os import path

CERTS = path.join(path.expanduser('~'), '.docker', 'machine', 'certs')

tls_config = tls.TLSConfig(
    client_cert=(path.join(CERTS, 'cert.pem'), path.join(CERTS,'key.pem')),
    ca_cert=path.join(CERTS, 'ca.pem'),
    verify=True
#verify=False
)
client = docker.Client(base_url='https://192.168.99.100:2376', tls=tls_config)

Problem

When I try to run this code (running something like print client.containers() on the next line), I get this error:

requests.exceptions.SSLError: hostname '192.168.99.100' doesn't match 'localhost'

I've been trying to follow the github issue on a similar problem with boot2docker, ie. the old version of docker-machine, but I don't know much about how SSL certificates are implemented. I tried adding 192.168.99.100 localhost to the end of my /etc/hosts file as suggested in the github issue, but that did not fix the issue (even after export DOCKER_HOST=tcp://localhost:2376).

Maybe connecting via the certificates is not the way to go for docker-machine, so any answers with alternative methods of connecting to a particular docker-machine via docker-py are acceptable too.

UPDATE Seems like v0.5.2 of docker-machine tries to solve this via the --tls-san flag for the create command. Need to verify but installation via brew is still giving v0.5.1, so I'll have to install manually.


Solution

  • I installed docker-machine v0.5.2 as detailed in the release on github. Then I just had to create a new machine as follows:

    $ docker-machine create -d virtualbox --tls-san <hostname> <machine-name>
    

    Then I added <hostname> <machine-ip> to /etc/hosts. The code worked after that

    from docker import Client
    import docker.tls as tls
    from os import path
    
    CERTS = path.join(path.expanduser('~'), '.docker', 'machine', 'machines', <machine-name>)
    
    tls_config = tls.TLSConfig(
        client_cert=(path.join(CERTS, 'cert.pem'), path.join(CERTS,'key.pem')),
        ca_cert=path.join(CERTS, 'ca.pem'),
        verify=True
    )
    client = docker.Client(base_url='https://<machine-ip>:2376', tls=tls_config)
    

    where I replaced <machine-name> in the CERTS path and replaced <machine-ip> in the base_url.