How to set docker-machine env for fabric local() commands

I’m trying to run commands against a docker-machine cloud provider, and so I need to take the contents of the command docker-machine env digitalocean which is typically as follows:

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://1.2.3.4:2376"
export DOCKER_CERT_PATH="/Users/danh/.docker/machine/machines/digitalocean"
export DOCKER_MACHINE_NAME="digitalocean"
# Run this command to configure your shell:
# eval "$(docker-machine env digitalocean)"

and use the above as a shell prefix, such as:

  • Can't communicate with simple Docker Node.js web app
  • Dockerfile manual install of multiple deb files
  • Akka 2.5 Distributed Data on Docker + Alpine Linux
  • Set Docker_Opts in centos
  • Update Docker container after making changes to image
  • docker install with tcp enabled 0.0.0.0
  • print 'outside with:' + local('echo $DOCKER_HOST')
    with prefix(local('docker-machine env digitalocean', capture=True)):
        print 'inside with:' + local('echo $DOCKER_HOST')
    with prefix('DOCKER_HOST="tcp://1.2.3.4:2376"'):
        print 'inside with (manual):' + local('echo $DOCKER_HOST')
    

    However this instead returns:

    outside with:tcp://192.168.99.100:2376
    inside with:
    inside with (manual):tcp://1.2.3.4:2376
    

    The only way I can see to get past this is to rip apart the result of local('docker-machine env digitalocean') manually. Surely there is a more fabric-esque way however?

  • docker cp doesn't work for this mysql container
  • How to deploy Spark,That it can make the highest resource utilization
  • How do you set-up Mongo replica set on Kubernetes?
  • akka cluster nodes behind NAT (using docker)
  • Docker Volume Access Error
  • How to use/link remote postgres db with django docker implementation
  • 2 Solutions collect form web for “How to set docker-machine env for fabric local() commands”

    Well, here’s the solution I’ve gone with so far, feels a bit hacky though:

    def dm_env(machine):
        """
        Sets the environment to use a given docker machine.
        """
        _env = local('docker-machine env {}'.format(machine), capture=True)
        # Reorganize into a string that could be used with prefix().
        _env = re.sub(r'^#.*$', '', _env, flags=re.MULTILINE)  # Remove comments
        _env = re.sub(r'^export ', '', _env, flags=re.MULTILINE)  # Remove `export `
        _env = re.sub(r'\n', ' ', _env, flags=re.MULTILINE)  # Merge to a single line
        return _env
    
    @task
    def blah():
        print 'outside with: ' + local('echo $DOCKER_HOST')
        with prefix(dm_env('digitalocean')):
            print 'inside with: ' + local('echo $DOCKER_HOST')
    

    Outputs:

    outside with: tcp://192.168.99.100:2376
    inside with: tcp://1.2.3.4:2376
    

    Another way to get the required information is to use formatting templates for the output of the docker-machine inspect command, as also shown in the documentation.

    Note that curly brackets in Python strings need to be escaped by doubling them, so you end up having four opening and closing brackets each time.

    machine_name = dev
    machine_ip = local("docker-machine inspect --format='{{{{.Driver.IPAddress}}}}' {0}".format(machine_name), capture=True)
    machine_port = local("docker-machine inspect --format='{{{{.Driver.EnginePort}}}}' {0}".format(machine_name), capture=True)
    machine_cert_path = local("docker-machine inspect --format='{{{{.HostOptions.AuthOptions.StorePath}}}}' {0}".format(machine), capture=True)
    

    Now, you can use the shell_env context manager in order to temporarily point your Docker daemon to a remote machine by setting the according environment variables:

    from fabric.api import shell_env
    with shell_env(DOCKER_TLS_VERIFY='1',
                   DOCKER_HOST='tcp://{0}:{1}'.format(machine_ip, machine_port),
                   DOCKER_CERT_PATH=machine_cert_path,
                   DOCKER_MACHINE_NAME=machine_name):
    
        # will print containers on the remote machine
        local('docker ps -a')
    
    # will print containers on your local machine 
    # since environment switch is only valid within the context manager
    local('docker ps -a') 
    
    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.