How to Start a Docker Host in the Cloud by Using Docker Machine: Complete Provisioning Guide

How to Start a Docker Host in the Cloud by Using Docker Machine

Before Docker Compose and Kubernetes largely took over cloud provisioning workflows, I used Docker Machine to spin up remote Docker hosts on cloud providers with a single command. Docker Machine is now a legacy, community-maintained tool — Docker Inc. archived active development years ago in favor of cloud-native provisioning (Terraform, cloud CLIs, managed Kubernetes) — but it still works, still ships useful concepts about how a “Docker host” is really just a machine running the Docker daemon reachable over the network, and it’s still genuinely handy for quick single-VM Docker hosts or for understanding what tools like Docker Desktop’s VM layer are doing under the hood.

What Docker Machine Actually Does

Docker Machine provisions a virtual machine (locally or on a cloud provider), installs Docker Engine on it, generates TLS certificates for secure remote access, and configures your local Docker CLI to point at that remote daemon instead of your local one. Once configured, ordinary docker run, docker build, and docker ps commands transparently execute against the remote host.

Prerequisites

  • Docker Machine binary installed locally
  • An account and API credentials with a supported cloud provider (I’ll use DigitalOcean for this walkthrough, though AWS, Azure, GCP, and others are supported via different drivers)
  • Docker CLI installed locally

Step 1: Install Docker Machine

curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-$(uname -s)-$(uname -m) \
  -o /usr/local/bin/docker-machine
chmod +x /usr/local/bin/docker-machine
docker-machine version
docker-machine version 0.16.2, build bd45ab13

Step 2: Create a Cloud API Token

For DigitalOcean, I generate a personal access token from the account dashboard, then export it:

export DO_TOKEN=your_digitalocean_api_token

Step 3: Provision a Docker Host in the Cloud

docker-machine create \
  --driver digitalocean \
  --digitalocean-access-token $DO_TOKEN \
  --digitalocean-region nyc3 \
  --digitalocean-size s-2vcpu-4gb \
  cloud-docker-host

Expected output:

Running pre-create checks...
Creating machine...
(cloud-docker-host) Creating SSH key...
(cloud-docker-host) Creating Digital Ocean droplet...
(cloud-docker-host) Waiting for IP address to be assigned to the Droplet...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Provisioning created instance...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect Docker to this machine, run: docker-machine env cloud-docker-host

Under the hood, this created a droplet, installed Docker Engine on it, generated a certificate authority plus client/server certificates, and configured the remote Docker daemon to only accept TLS-authenticated connections.

Step 4: Point Your Local Docker CLI at the Remote Host

docker-machine env cloud-docker-host
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://198.51.100.42:2376"
export DOCKER_CERT_PATH="/home/user/.docker/machine/machines/cloud-docker-host"
export DOCKER_MACHINE_NAME="cloud-docker-host"
# Run this command to configure your shell:
# eval $(docker-machine env cloud-docker-host)

Apply it:

eval $(docker-machine env cloud-docker-host)

Now any docker command runs against the cloud host instead of my laptop.

Step 5: Verify and Use the Remote Host

docker info
Server:
 ...
 Operating System: Ubuntu 22.04.4 LTS
 Kernel Version: 5.15.0-101-generic
 Name: cloud-docker-host

Run a container exactly as if it were local:

docker run -d -p 8080:80 --name remote-nginx nginx:latest
curl http://198.51.100.42:8080
<!DOCTYPE html>
<html>
<head><title>Welcome to nginx!</title></head>
...

Note that the port is exposed on the remote host’s public IP, so I’d normally lock this down with cloud firewall rules rather than leaving arbitrary ports open to the internet.

Step 6: Switch Back to Local Docker

eval $(docker-machine env -u)
docker info | grep "Name:"
Name: my-local-laptop

Managing Multiple Machines

docker-machine ls
NAME                 ACTIVE   DRIVER          STATE     URL
cloud-docker-host    -        digitalocean    Running   tcp://198.51.100.42:2376
docker-machine ssh cloud-docker-host

Drops me into an interactive shell on the remote VM itself.

docker-machine stop cloud-docker-host
docker-machine start cloud-docker-host
docker-machine rm cloud-docker-host

rm destroys the actual cloud VM, not just the local reference to it — a genuinely destructive action worth double-checking before running.

Internal Working: How Docker Machine Sets Up Secure Remote Access

Docker Machine’s core job, beyond calling the cloud provider’s API to boot a VM, is establishing mutual TLS between my local Docker CLI and the remote Docker daemon. It generates a local certificate authority (stored under ~/.docker/machine/certs/), issues a server certificate for the remote daemon and a client certificate for my CLI, and configures the remote dockerd to listen on TCP port 2376 with --tlsverify and the appropriate cert paths. This is precisely why exposing Docker’s daemon socket over the network is normally considered dangerous — full API access equals full control over the host — but Docker Machine automates the TLS layer that makes doing so at least authenticated and encrypted rather than wide open.

Networking Considerations

The remote daemon listens on TCP 2376 by default; any container ports I publish with -p bind to the cloud VM’s network interfaces, meaning published ports are reachable from the public internet unless the cloud provider’s firewall/security group restricts them. I always pair Docker Machine hosts with the cloud provider’s native firewall (DigitalOcean Cloud Firewalls, AWS Security Groups, etc.) rather than relying on Docker alone for network security.

Storage Considerations

Docker Machine provisions whatever default disk size the chosen VM plan includes; for anything beyond quick experiments, I resize the droplet or attach a separate block storage volume and mount it at /var/lib/docker before running heavy workloads, since the default disk fills up quickly with pulled images.

Security Considerations

  • Never leave the Docker daemon’s TCP port reachable without TLS — Docker Machine enables this by default, but always double check --tlsverify is actually active with docker-machine inspect.
  • Restrict cloud firewall rules to only the ports genuinely needed (2376 for Docker API from your IP, plus whatever application ports you intentionally publish).
  • Rotate or revoke certificates and destroy machines you no longer use — a forgotten cloud VM with a working Docker Machine TLS setup is a real, lingering attack surface.
  • Docker Machine is unmaintained upstream; for anything long-term, prefer actively maintained provisioning tools (Terraform + cloud-init, or managed container services).

Troubleshooting

“Error creating machine: exit status 1” during creation Usually an API token issue or a region/size combination not available on the account. Re-run with --debug for verbose output:

docker-machine --debug create --driver digitalocean ...

“Unable to connect to the Docker daemon” after eval Confirm the machine is actually running:

docker-machine status cloud-docker-host

Certificates expired or corrupted Regenerate them:

docker-machine regenerate-certs cloud-docker-host

Monitoring

docker-machine ls
docker-machine ssh cloud-docker-host "docker stats --no-stream"

For anything running long-term, I’d pipe metrics into a real monitoring stack (Prometheus node-exporter and cAdvisor) rather than relying on ad hoc SSH checks.

Best Practices

  • Treat Docker Machine hosts as disposable — destroy and recreate rather than patching in place.
  • Always pair with cloud-native firewall rules.
  • Use docker-machine env scoping carefully in scripts to avoid accidentally running commands against the wrong host.
  • For anything beyond a single quick VM, move to Terraform, cloud-init, or a managed Kubernetes service — Docker Machine is a convenience tool for one-off hosts, not a fleet management system.

Summary

Docker Machine automates exactly two things: booting a cloud VM through a provider’s API, and wiring up TLS-secured remote access so my local Docker CLI can control that VM’s daemon as if it were local. It’s a legacy tool now, but a great lens for understanding what a “Docker host” really is — just a machine with dockerd listening securely over the network — and it’s still perfectly usable for spinning up a single Docker host on the cloud quickly.

References

  • Docker Machine documentation (archived): https://github.com/docker/machine
  • Docker Machine driver reference: https://github.com/docker/docker.github.io/tree/master/machine/drivers
  • Docker daemon TLS configuration: https://docs.docker.com/engine/security/protect-access/
  • DigitalOcean API documentation: https://docs.digitalocean.com/reference/api/
Total
0
Shares

Leave a Reply

Previous Post
How T Set Up a Local Docker Host by Using Vagrant

How to Set Up a Local Docker Host by Using Vagrant: Development Environment Configuration Guide

Next Post
How to Use Docker Experimental Binaries

How to Use Docker Experimental Binaries: Enabling and Testing New Docker Features Guide

Related Posts