Dancing on a cloud made of pearls

Thanks to a post on Hacker News, I got access to the beta test for DotCloud. In this blog post, I show how I got started and successfully deployed a small Perl Dancer web app to the service.

I was extremely pleased with how easy it was to do the above, and wanted to share it!

After creating the account on DotCloud, a quick and painless endeavour, I followed along their first steps tutorial, making sure I’d change the various steps in order to deploy a Perl Dancer webapp.

Here is the transcript of the first steps of the tutorial, which did not change for me:

$ sudo aptitude install python-setuptools
[...]

$ sudo easy_install dotcloud
[...]

$ dotcloud
Warning: /home/okram/.dotcloud/dotcloud.conf does not exist.
Enter your api key (You can find it at http://www.dotcloud.com/account/settings): XXXXXXXXXXXXXXXXXXXXXXXXX
error: usage: dotcloud [-h]
    {status,info,run,logs,deploy,setup,list,alias,ssh,destroy,push,rollback,create,restart}
    ...

At this point I just went to the linked URL, and copy/pasted my API key. Nothing strange so far.

I then created a new namespace, “weasel”, and an endpoint “www”. Lastly, I checked it was created:

$ dotcloud deploy -t perl weasel.www
Created "weasel.www".

$ dotcloud info weasel.www
cluster: wolverine
config: {}
created_at: 1304117136.2035949
name: weasel.www
namespace: weasel
state: booting
type: perl

Time for code! I created a new Git repo, and edited some files. The full listing (heh!) will be at the end of the article.

$ mkdir -p GIT/weasel/www
$ cd !$
$ git init
Initialized empty Git repository in /home/okram/GIT/weasel/www/.git/
$ vi -p myapp.pl Makefile.PL app.psgi
3 files to edit
$ git add * ; git commit -am "Initial commit"
[...]

The Makefile.PL contained Dancer as a prerequisite, as the myapp.pl did not make use of any other Perl module.

It came the time to try deploying the webapp to dotcloud; easy! Dotcloud took care of installing the Dancer prerequisite, along with all the dependencies, and then tried to start the app.

$ dotcloud push weasel.www .
# upload . ssh://dotcloud@uploader.dotcloud.com:1060/weasel.www
# git
Warning: Permanently added '[uploader.dotcloud.com]:1060,[174.129.15.77]:1060' (RSA) to the list of known hosts.
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 533 bytes, done.
Total 5 (delta 0), reused 0 (delta 0)
To ssh://dotcloud@uploader.dotcloud.com:1060/weasel.www
* [new branch]      master -> master
Scheduling build
Fetching logs...
Warning: Permanently added '[www.weasel.dotcloud.com]:3254,[174.129.17.131]:3254' (RSA) to the list of known hosts.
-- Build started...
Makefile.PL
app.psgi
myapp.pl
Fetched code revision e4d8d81
--> Working on .
Configuring /home/dotcloud/e4d8d81 ... OK
==> Found dependencies: Dancer
--> Working on Dancer
Fetching http://search.cpan.org/CPAN/authors/id/X/XS/XSAWYERX/Dancer-1.3030.tar.gz ... OK
Configuring Dancer-1.3030 ... OK
==> Found dependencies: HTTP::Server::Simple::PSGI, HTTP::Body, MIME::Types
--> Working on HTTP::Server::Simple::PSGI
[...]
Successfully installed MIME-Types-1.31
Building Dancer-1.3030 ... OK
Successfully installed Dancer-1.3030
<== Installed dependencies for .. Finishing.
8 distributions installed
uwsgi: stopped
uwsgi: ERROR (abnormal termination)
Connection to www.weasel.dotcloud.com closed.

Oh-oh! Something went wrong! I checked the log files to see what was it:

$ dotcloud logs weasel.www
#  tail -F /var/log/{supervisor,nginx}/*.log 
[...]
==> /var/log/supervisor/uwsgi.log <==
[...]
Plack::Request is needed by the PSGI handler at /home/dotcloud/perl5/lib/perl5/Dancer.pm line 334
Compilation failed in require at (eval 3) line 1.
[...]

That’s it: it’s clearly missing Plack::Request to be able to handle PSGI requests. No problem; just add it to the Makefile.PL and deploy again! This will install the new dependency, and hopefully the service will start!

$ vi Makefile.PL
$ git commit -am "Add Plack::Request as prerequisite also"
[master faa342f] Add Plack::Request as prerequisite also
1 files changed, 1 insertions(+), 0 deletions(-)
$ dotcloud push weasel.www .
# upload . ssh://dotcloud@uploader.dotcloud.com:1060/weasel.www
# git
Warning: Permanently added '[uploader.dotcloud.com]:1060,[174.129.15.77]:1060' (RSA) to the list of known hosts.
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 381 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To ssh://dotcloud@uploader.dotcloud.com:1060/weasel.www
   e4d8d81..faa342f  master -> master
Scheduling build
Fetching logs...
Warning: Permanently added '[www.weasel.dotcloud.com]:3254,[174.129.17.131]:3254' (RSA) to the list of known hosts.
-- Build started...
[...]
Fetched code revision faa342f
--> Working on .
Configuring /home/dotcloud/faa342f ... OK
==> Found dependencies: Plack::Request
--> Working on Plack::Request
[...]
Successfully installed Devel-StackTrace-AsHTML-0.11
Building Plack-0.9976 ... OK
Successfully installed Plack-0.9976
<== Installed dependencies for .. Finishing.
12 distributions installed
uwsgi: started
Connection to www.weasel.dotcloud.com closed.

And so it did! Let’s see if my webapp really worked:

$ curl http://www.weasel.dotcloud.com/
Why, hello there!

$ curl http://www.weasel.dotcloud.com/test-123
Hello test123!

Indeed it did!

There you go, an easy way to deploy a Dancer webapp to the cloud!

Here are the sample files I used:

$ cat Makefile.PL
#!/usr/bin/env perl
use ExtUtils::MakeMaker;
WriteMakefile(
    PREREQ_PM => {
        'Dancer' => '1.3030',
        'Plack::Request' => '0.9976',
    },
);


$ cat myapp.pl 
#!/usr/bin/env perl
use Dancer;
get '/' => sub {
    return "Why, hello there!\n";
};
get '/:name' => sub {
    my $name = params->{name};
    $name =~ s/[^a-z0-9 ]//i;
    return "Hello $name!\n";
};
dance;

$ cat app.psgi 
require 'myapp.pl';

Really, really easy! Thanks Dotcloud! And, thanks CPAN and CPAN authors, without which the above certainly would not have been possible!

1 Comment

Nice! I copied your instructions and they worked very well :)


http://www.kaokun.dotcloud.com/


I did notice a small bug in your code:


$name =~ s/[^a-z0-9 ]//i;


Should read:


$name =~ s/[^a-z0-9 ]//ig;


- Alex

Leave a comment

About Marco Fontani

user-pic Slicing and splicing onions