We removed our free Sandbox April 25th.
You can read more on our blog.

nodeSocket Welcome

Hello! And welcome to the dotCloud Platform. We hope you’ll like running your Node.js code here. To help you get started, we’ve put together a few notes on how some nodeSocket ideas map to dotCloud.

If you’d rather get started with doing instead of reading, you can skip ahead to the Hands On section.

Translating Terms

nodeSocket Term dotCloud Term Notes
Machines Service Containers / Instances You won’t have root access on the service container, but you can still install packages. You’re not running in a single VM. Instead, each service runs in its own Linux Container, lxc, each probably on a different host machine. The dotCloud platform automatically configures containers to run your services. The containers are running Ubuntu 10.04LTS
Gears approots Each approot directory holds all the code for one service. It is a subdirectory of your current application directory. In each service container, ~/current/ points to the approot you defined for that service in dotcloud.yml. You can scale each service “horizontally” to run multiple copies.
Lever dotCloud Builder + Supervisor The dotCloud Builder is separate from your containers. Builds happen on a different host machine. But, similar to Lever, the dotCloud Builder reads a configuration file and sets up all the networking and containers. Within the container, services like Node.js applications may use Supervisor to start. Supervisor is not proprietary. It will start a process and restart it if it exits unexpectedly.
.torque dotcloud.yml There is only one dotcloud.yml file in the root of your application directory tree, and it defines all of your services. Together this defines your stack. dotCloud runs more than Node.js! Your services could include a cache, multiple databases, and code in other languages. Each service runs in a separate service container, probably on a different host machine. Never assume ‘localhost’ will connect you to a service.

Some Differences

We don’t have a public REST API like nodeSocket. Instead we offer a command line interface (CLI) called dotcloud written in Python. You’ll use the dotCloud CLI to create applications and push your code up to the dotCloud platform for building and deployment.

We don’t run git in your service containers, but our CLI knows how to work with git on your local system, and we track the revisions we push. We do not recommend using SFTP for deployments because of how our platform builds and deploys. Like nodeSocket, we recognize and use package.json files to install dependent packages via npm during a push.

Warning

On nodeSocket your Machine and Gears behaved like a virtual machine, persisting between pushes. On dotCloud, every time you push, you get new Service Containers!

That difference means that even though you can ssh into your containers and make changes manually, these changes will disappear upon your next push. Your push must include everything you need to run, including any changes you’d like to make to directory structures, cron jobs, etc. Anything you can do via the command line you should be able to automate as part of a build hook, one of three scripts we run as part of the build process.

FAQs

What’s the benefit? New containers mean you can push new code with zero downtime. We bring up your new containers, install your code, get it running, and then switch over traffic to the new containers, finally destroying the old containers when the traffic has switched to your newest code. New containers also mean we can replicate your service on demand to give you more running copies to handle more traffic or do more work.

What about uploaded files? We recommend you store your persistent data in a database or on S3, accessed directly via a library and not s3fs. If you just want a quick and dirty way to store files persistently on your server (without losing them between pushes), then you can store them in ~/data. If you create that directory, then we will treat it in a special way: we will look for it and move it from the old container to the new container during deployment.

Warning

There are two significant flaws with using ~/data to store files between pushes:

1. Your pushes will take down your application. Pushes will not be seamless. Since the files must be moved from the old container to the new container, we must first halt the old container (and any internet traffic it was receiving) and move to the new container (which isn’t running yet and cannot receive internet traffic).

2. Each container has its own ~/data, so if you scale your front end to multiple containers, and someone uploads to container 0, that file will not be available on container 1.

Do database services get destroyed during a push? No, we don’t destroy these every push – they’re special. Once they are created, we don’t change these containers unless you destroy them yourself. We can scale MySQL and MongoDB for you to provide redundancy and automatic fail-over.

Doesn’t starting with a new container mean my builds will take forever? It would if we built from scratch each time, but we preserve the results of your previous build to use as a starting state. The build happens on a separate build machine which has a lot of memory (probably more than your service container). Once we’ve processed your code and all its dependent packages, we take a snapshot of the file system in that container and destroy the build container. We then create as many new containers as you’ve requested for that service and unpack the build snapshot into each one, starting up each one. When you push again, we again create a new container on the build machine, but this time we initialize the file system with the snapshot we took at the end of the previous build, so all the dependencies and build products are already there. Then we apply the changes you’ve made in your newly uploaded code, build, snapshot, and deploy again. If you ever want to build without your previously-fetched dependencies and code, use dotcloud push --clean.

Hands On

Note

tl;dr (for the truly impatient):

Prepare Your Code

You should make sure that all of your code is under one directory tree, and if you are using git, that everything is checked-in locally. The dotCloud CLI knows how to work with git, including honoring .gitignore, but it will not pull code from other repositories. You’ll have to pull that code locally.

Let’s presume your nodesocket application looks like this:

nodesocketapp/
├── Gear1
│   ├── file1.js
│   ├── file2.js
│   ├── package.json
│   ├── server.js
│   └── .torque
└── Gear2
    ├── file1.js
    ├── file2.js
    ├── package.json
    ├── server.js
    └── .torque

Then your dotCloud application will look like this:

dotcloudapp/
├── dotcloud.yml <--- NEW
├── Gear1
│   ├── file1.js
│   ├── file2.js
│   ├── package.json
│   ├── server.js
│   └── supervisord.conf <-- NEW
└── Gear2
    ├── file1.js
    ├── file2.js
    ├── package.json
    ├── server.js
    └── supervisord.conf <-- NEW

Move Configuration From .torque to dotcloud.yml and supervisord.conf Files

Given this .torque file for Gear1:

{
     "start": "server.js",
     "route": "127.0.0.1:3535",
     "env": {
         "port": 3535,
         "mongo-host": "pearl.mongohq.com",
         "mongo-port": 28936
     },
     "parameters": [
         "--development",
         "--verbose"
      ]
 }

Some of this configuration will go into the dotcloud.yml file at the root of your application source tree, and some will go into a supervisord.conf file in the Gear1 directory.

Example dotcloudapp/dotcloud.yml:

gear1:
  type: nodejs
    approot: Gear1
  config:
    node_version: v0.8.x
  environment:
    MONGO_HOST: pearl.mongohq.com
    MONGO_PORT: 28936
gear2:
  type: nodejs
  approot: Gear2
  config:
    node_version: v0.8.x

Note that it is critical to use space, not tabs in the dotcloud.yml file.

Example dotcloudapp/Gear1/supervisord.conf:

[program:node]
command = node server.js --development --verbose
directory = /home/dotcloud/current

The dotCloud Builder will create a symbolic link between /home/dotcloud/current and the directory you specified as approot in dotcloud.yml, so “current” is always the approot of the current application.

Update Your Code to Listen on Port 8080

If your Node code provides a service via HTTP, then it must listen to port 8080.

If your Node code provides a service via TCP then you must request a port in your dotcloud.yml file and one will be assigned. You cannot specify the port number. You can read the assigned port number from a file you will find generated on your service: /home/dotcloud/environment.json

Create a dotCloud Account

https://www.dotcloud.com/register.html

Remember the username and password and password you create. You’re going to need it with the CLI.

Install the dotCloud CLI

We strongly encourage you to use virtualenv when working with Python tools like the dotCloud CLI, but it is not a requirement. Once you have a Python environment working on your system:

$ pip install dotcloud
$ dotcloud setup
$ dotcloud check

Create a New Application and Push

# Change to the local directory to where we have our code
$ cd dotcloudapp
$ dotcloud create --git portedapp
# Choose “Y” to connect this directory with the “portedapp” application.
$ dotcloud push

And you’re done! If the push got disconnected from the push logs (unfortunately that’s been happening a lot recently), you can reconnect with dotcloud dlogs latest and get the status. If there is a problem, or you have any questions, please email us at support@dotcloud.com using your dotcloud account email address, or let us know the URL to your application.

We’re happy you’re here!

/dotCloud Developer Support