Tutorial

How To Use the API to Deploy Droplets From a Master Snapshot

Published on February 27, 2015
How To Use the API to Deploy Droplets From a Master Snapshot

Introduction

In this tutorial we will create a master snapshot image with our software and configuration and then use the DigitalOcean API automate deployment of droplets using this image. The examples in this tutorial will be using the official DigitalOcean API client for Ruby DropletKit.

Prerequisites

  • Ruby should be installed on the computer you will be using to connect to the API.
  • The DropletKit gem should be installed in this environment as well.
  • You should have generated an API token for your scripts to use.

Step One: Create Your Master Image

In this tutorial we will create a master image based on the LAMP One-Click Image, set up our default configuration and then use it to create a snapshot image. Snapshots cost $0.05 per gigabyte per month, based on the amount of utilized space within the filesystem. We will be able to deploy multiple instances of our customized LAMP stack using the DigitalOcean API.

Create a new droplet

We will start by creating a new droplet named lamp-master from the control panel selecting the LAMP image in the Applications tab. This image will provide us with a pre-built Ubuntu 14.04 server with Apache, MySQL and PHP.

When creating the droplet we will use to generate our master snapshot image it is important to select the smallest droplet plan we can. Once we create our snapshot it can only be used to create droplets on the same plan or a larger one. For example, if we create our master snapshot using a 1GB droplet we could then use it to launch droplets on the 1GB, 2GB or other larger plans but we would not be able to launch a droplet with 512MB RAM from this snapshot.

Once our new droplet has been created, use an SSH client to connect to it.

Initial Configuration

Now that we are connected to our new droplet we can configure any settings or install any packages that we want to have on all droplets deployed from our master image. In this case we will install two extra php modules; curl and Imagemagick.

sudo apt-get update
sudo apt-get install php5-curl php5-imagick

Creating the Snapshot

Now that we have added the additional software we want we can power off our droplet and create our snapshot. While it is possible to take a snapshot of a running system, powering down ensures that the filesystem is in a consistent state:

sudo poweroff

While we could create our snapshot from the control panel, for the purposes of this tutorial we will use the API from this point forward to work with our DigitalOcean account. These examples can be run with interactive Ruby (irb) or added to a script and run with the ruby command. The first step will be to include the DropletKit client.

require 'droplet_kit'
token='[your api token]'
client = DropletKit::Client.new(access_token: token)

In order to create a snapshot from the API we will need to get the id for our master droplet. We can do this by making a call to the droplets endpoint of the API.

droplets = client.droplets.all
droplets.each do |droplet|
  if droplet.name == "lamp-master"
    puts droplet.id
  end
end

This snippet of code will make a call to the droplets endpoint of the API and loop through the droplets in our account looking for one with the name lamp-master. When it finds it, the script will then display the ID number for this droplet.

Now that we have our droplet ID number we can tell the API to create a snapshot of this droplet by passing the droplet ID to the snapshot action of the droplet endpoint. In addition to the droplet ID we will also pass a snapshot name which will be used for our new image. In this case we have decided to name our snapshot lamp-image.

client.droplet_actions.snapshot(droplet_id: '1234567', name: 'lamp-image')

The snapshot request we made will return an event ID number which can be used to track the status of the snapshot process. This tutorial will provide more information on using event IDs.

Step Two: Deploying Droplets from our Snapshot

We have now created a master snapshot image we can use to deploy droplets with our configuration. As we did with our droplet, we will now need to query the API to get the image ID for our new snapshot.

images = client.images.all(public:false)
images.each do |image|
  if image.name == "lamp-image"
    puts image.id
  end
end

As with our droplet identification example above this code will loop through the snapshot and backup images on our account and display the ID for the image named lamp-image.

Now that we have our image’s ID number we can start deploying droplets. The following code will create a new 2GB droplet using our master snapshot in the New York 3 region.

Note that our snapshot image needs to be present in the region we specify for our droplet creation. You can transfer an image to additional regions via the control panel or through the API’s image endpoint.

droplet = DropletKit::Droplet.new(name: 'my-lamp-server', region: 'nyc3', size: '2gb', image: '1234567')
client.droplets.create(droplet)

Step Three: Customization with User-Data

We can now deploy new droplets with our custom configuration using the API but we may want to further customize our new droplets individually. We can perform additional customization by sending user-data to our droplets when we create them.

For this example we will pre-load a custom index.html file on our new droplet including it’s name.

sitename = "example.org"
userdata = "
#cloud-config

runcmd:
- echo '<html><head><title>Welcome to #{sitename} </title></head><body><h1>This is #{sitename}</h1></body></html>' > /var/www/html/index.html
"
droplet = DropletKit::Droplet.new(name: sitename, region: 'nyc3', size: '2gb', image: '1234567', user_data: userdata)
client.droplets.create(droplet)

In this example we are simply using the echo command inside our new droplet to drop some HTML into an index.html file in the web root. By using other commands you could choose to configure new virtualhosts directly on your droplet, pull down additional configuration details from a remote server or do just about anything you could do via an ssh connection. You can learn more about user-data here.

Step Four: Putting it Together

Now that we can deploy droplets based on our snapshot image via the API and customize their contents lets take it a step further and create an interactive script to launch new droplets based on our image. The following script assumes that we have already created our snapshot image and have it’s ID available.

require 'droplet_kit'
token='[Your API Token]'
client = DropletKit::Client.new(access_token: token)
region = 'nyc3'
image_id = '1234567'
droplet_size = '2gb'

puts "Enter a name for your new droplet:"
sitename = gets.chomp

userdata = "
#cloud-config

runcmd:
- echo '<html><head><title>Welcome to #{sitename} </title></head><body><h1>This is #{sitename}</h1></body></html>' > /var/www/html/index.html
"
sitename.gsub!(/\s/,'-')
droplet = DropletKit::Droplet.new(name: sitename, region: region, size: droplet_size, image: image_id, user_data: userdata)
client.droplets.create(droplet)

Code Breakdown

This script first includes the DropletKit client and initializes a new client connection using the API token you supply.

require 'droplet_kit'
token='[Your API Token]'
client = DropletKit::Client.new(access_token: token)

We then specify a few options for our droplet including the region, droplet size and the ID for our master snapshot image.

region = 'nyc3'
image_id = '1234567'
droplet_size = '2gb'

Then we prompt the user to provide a name for the new droplet and include this information in the user-data our script will provide to the creation process.

puts "Enter a name for your new droplet:"
sitename = gets.chomp

userdata = "
#cloud-config

runcmd:
- echo '<html><head><title>Welcome to #{sitename} </title></head><body><h1>This is #{sitename}</h1></body></html>' > /var/www/html/index.html
"

Once we have included our site name in our index.html page we need to sanitize it to make sure it can be used as a droplet name. Since droplet names cannot have spaces in them we will replace any spaces with dashes.

sitename.gsub!(/\s/,'-')

Then we bring all these variables together and submit our request to create the new droplet.

droplet = DropletKit::Droplet.new(name: sitename, region: region, size: droplet_size, image: image_id, user_data: userdata)
client.droplets.create(droplet)

Next Steps

Using the API we can create custom droplets on demand and include our own settings or files at creation. You may choose to expand on these basics by adding additional functionality to this script. Possible improvements include.

  • Using the DNS endpoint of the API to auto-configure DNS records for your new droplets when they are launched.

  • Prompting the user for additional inputs such as region or droplet size.

  • Using user-data runcmd calls to download web content to your new droplets or to populate MySQL databases.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
3 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I don’t know what went wrong but i am trying to create a droplet from an ubuntu image but this code is creating a coreOs droplet every time . Please help

droplet = DropletKit::Droplet.new(name: 'thisisname', size: '512mb', region: 'sgp1', image: 'somethinghere', ssh_keys: ["something"])

@client.droplets.create(droplet)

Hi, thanks for responding. I’m not sure what I was doing wrong there, but I have since gotten it to work. So all appears to be working as expected. :)

Does the original droplet still have to exist?

I’m trying to resurrect an old, deleted droplet. I made a snapshot of it, and it seems that I can bring up a new droplet from that snapshot from the UI. However, I can’t get it working from the API. I’ve looked at the “…/v2/images?private=true” endpoint to get the id for the snapshot, but passing that as the argument to the “image” parameter when POSTing to v2/droplets results in a “You specified an invalid image for Droplet creation” error. Specifically this is what I tried (I have $DO_TOKEN and $IMAGE_ID set correctly in my environment):

$ curl -H "Authorization: Bearer $DO_TOKEN" -H "Context-Type: application/json" -X POST -d '{"name": "test", "region": "nyc3", "size": "1gb", "image": "$IMAGE_ID"}' "https://api.digitalocean.com/v2/droplets"
{"id":"unprocessable_entity","message":"You specified an invalid image for Droplet creation."}

Is it possible to create a new droplet from a snapshot of a deleted droplet via the API? If so, what could I be doing incorrectly?

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel