doctl is the official command-line interface for DigitalOcean, letting you manage your Droplets, Spaces, and other resources without touching the web console.
Imagine you need to spin up a new Droplet, assign it a static IP, and then attach a volume. With doctl, this becomes a single, scriptable sequence.
# Create a new Droplet named 'my-app-server' in the 'nyc3' region, using Ubuntu 22.04 LTS, on a basic 2GB plan.
doctl compute droplet create my-app-server \
--region nyc3 \
--image ubuntu-22-04-x64 \
--size s-2vcpu-4gb
# Get the ID of the newly created Droplet (replace 'my-app-server' if you used a different name)
DROPLET_ID=$(doctl compute droplet list --no-header | grep my-app-server | awk '{print $1}')
# Create a new 50GB volume named 'my-app-data' in the 'nyc3' region.
doctl compute volume create my-app-data \
--region nyc3 \
--size 50
# Get the ID of the newly created volume
VOLUME_ID=$(doctl compute volume list --no-header | grep my-app-data | awk '{print $1}')
# Attach the volume to the Droplet
doctl compute volume attach $VOLUME_ID $DROPLET_ID
# List all Droplets to confirm
doctl compute droplet list
This isn’t just about convenience; it’s about reproducibility and automation. You can version control these commands in a shell script, ensuring that setting up a new environment is an exact, repeatable process, down to the specific Droplet size and region.
The core of doctl’s power lies in its declarative approach to resource management. When you issue a command like doctl compute droplet create, you’re not just sending a request; you’re defining the desired state of a resource. doctl then translates this into the necessary API calls to achieve that state.
Internally, doctl is a Go binary that communicates with the DigitalOcean API. It parses your commands, constructs the appropriate JSON payloads, and sends them over HTTP. The responses from the API are then parsed and presented back to you in a human-readable format, usually as tables or JSON.
The command structure is hierarchical: doctl <resource_type> <action> [options]. For example, doctl compute droplet list breaks down into:
doctl: The main executable.compute: The primary resource domain (as opposed tokubernetes,databases, etc.).droplet: The specific resource type withincompute.list: The action to perform on droplets.
When you execute doctl compute droplet create --size s-2vcpu-4gb --image ubuntu-22-04-x64 my-new-droplet, doctl takes the arguments, constructs a JSON object representing the desired Droplet configuration, and sends it to the DigitalOcean API’s /v2/droplets endpoint using a POST request. The API then handles the provisioning process, and doctl reports the outcome.
One of the less obvious, but incredibly useful, features is the ability to generate API requests without executing them. This is invaluable for debugging or understanding the exact payload being sent. For instance, to see what doctl would send to create a Droplet but not actually create it, you’d use the --dry-run flag (though this flag is not universally supported across all commands and is more common in tools that interact with Kubernetes APIs). For doctl, the closest you get is often inspecting the output of the commands themselves or using curl with the API directly after constructing the payload based on doctl’s behavior.
The doctl context and configuration are managed by a ~/.config/doctl/config.yaml file. This file stores your API token, default region, and other preferences. You can initialize this with doctl init and manage it with doctl config set <key> <value>. This allows you to set a default region so you don’t have to specify --region nyc3 every single time.
The next logical step after managing individual resources is to orchestrate them. You’ll find yourself wanting to group resources, manage their lifecycle as a unit, and potentially integrate this into CI/CD pipelines.