Cloud Foundry has significantly enhanced support for worker applications that perform background processing by allowing applications to run on CloudFoundry.com without the application container. Cloud Foundry applications are no longer limited to Web applications that respond to HTTP requests. Instead, they can be run as executable or “standalone” applications. A standalone application is one that does not require a provided framework or container.
Many developers create distributed applications that have workers to perform specific functions and communicate via a data or messaging system, such as those developed with Spring Batch, Spring Integration, Resque, or Delayed Job. Now Cloud Foundry supports running these worker components by allowing you to push a directory or single file without choosing a pre-defined framework. Simply provide the command required to run your script or executable, chose a runtime, and you’re done. Besides background processing functions, the standalone application support enables these other types of applications as well:
- Container-less non-Servlet applications, such as those developed with Netty or Grizzly
- Web apps that run with their own bundled containers, such as Jetty
Also in this series:
In this blog series, we will walk through several example deployments of standalone apps. We will start with a simple Hello World to illustrate the deployment steps. In future posts, we will show examples of worker apps, distributed apps, and bring-your-own-container and container-less Web apps. While the apps may vary in use case and implementation, the deployment procedure remains the same.
All of these apps are meant to be long-running, as with any other app on Cloud Foundry (meaning they can be scaled, will be monitored for health, restarted if crashed, etc.). We do not yet have support for short-lived background tasks or scheduled tasks. However, we encourage you to keep watching this space!
Getting Started with Standalone Apps on Cloud Foundry
First, install or update your Cloud Foundry command line tool (‘VMC’) to the latest version using the following command:
gem install vmc
You can verify that you got the right version using:
vmc -v
which should show the version to be 0.3.17 or higher.
Let’s start by deploying a simple Hello World Ruby application.
mycomp:$ cd simple-ruby-app mycomp:$ ls hello-world.rb mycomp:$ more hello-world.rb loop { puts 'Hello world' sleep 5 }
Since we need a long-running application, this script will print “Hello World” every 5 seconds until stopped. Let’s push this to Cloud Foundry using vmc:
mycomp:$ vmc push helloworld Would you like to deploy from the current directory? [Yn]: Detected a Standalone Application, is this correct? [Yn]: 1: java 2: node 3: node06 4: ruby18 5: ruby19 Select Runtime [ruby18]: Selected ruby18 Start Command: ruby hello-world.rb Application Deployed URL [None]: Memory reservation (128M, 256M, 512M, 1G, 2G) [128M]: How many instances? [1]: Create services to bind to 'helloworld'? [yN]: Would you like to save this configuration? [yN]: y Manifest written to manifest.yml. Creating Application: OK Uploading Application: Checking for available resources: OK Packing application: OK Uploading (1K): OK Push Status: OK Staging Application 'helloworld': OK Starting Application 'helloworld': OK
So, what just happened?
1. vmc detected that the app was a “Standalone Application” (due to the fact that no other Framework support was detected).
2. We were asked to provide a runtime. Since the app needs Ruby to run, we chose the “ruby18” runtime (which vmc detected as default).
3. We provided a command to use for starting the application. Since we’ve chosen a Ruby 1.8 runtime, we don’t need to provide the fully qualified path to Ruby. Cloud Foundry will automatically add Ruby 1.8 to the application’s path.
4. We chose “None” for the application URL. This will run the application without a Web port or URL. There are times when we will want a URL and Web port for a standalone application, as we’ll see in a later blog post.
5. vmc pushed the entire contents of the working directory to Cloud Foundry. Since we only had hello-world.rb in the directory, we could have also executed “vmc push –path ./hello-world.rb”. The –path option comes in handy when working with distribution zip files, as we’ll see in an upcoming post.
Let’s have a look at the application’s logs:
mycomp:$ vmc logs helloworld
====> /logs/stdout.log <====
Hello world
Hello world
As you can see, helloworld can be managed just like any other Cloud Foundry application:
mycomp:$ vmc instances helloworld +2 Scaling Application instances up to 3: OK mycomp:$ vmc instances helloworld +-------+---------+--------------------+ | Index | State | Start Time | +-------+---------+--------------------+ | 0 | RUNNING | 04/20/2012 04:47PM | | 1 | RUNNING | 04/20/2012 04:48PM | | 2 | RUNNING | 04/20/2012 04:48PM | +-------+---------+--------------------+
Let’s look at the logs again for two of the instances:
mycomp:$ vmc logs helloworld --instance 0 ====> /logs/stdout.log <==== Hello world Hello world mycomp:$ vmc logs helloworld --instance 1 ====> /logs/stdout.log <==== Hello world Hello world
Standalone app deployment manifest
Let’s take a look at the manifest file we generated with that vmc push:
mycomp:$ more manifest.yml --- applications: .: name: helloworld framework: name: standalone info: description: Standalone Application mem: 128M runtime: ruby18 command: ruby hello-world.rb url: mem: 128M instances: 1
Seems pretty straightforward. The app is deployed against a “standalone” framework, with a command and ruby18 runtime. To save time, we’ll be sure to save this manifest file for future deployments.
Tips and Tricks
You should now be able to deploy any long-running app that you can package, using any of Cloud Foundry’s provided runtimes. However, there are some tips and tricks to getting the best experience from Cloud Foundry:
1. Use the VCAP_APP_PORT environment variable if your application requires a web port.
2. Connect your application to Cloud Foundry services using provided libraries (see below) or the VCAP_SERVICES environment variable (value is in JSON).
JVM Applications
1. Package your application using a build plugin that creates a distribution zip file or directory.
Maven Appassembler, Gradle Application Plugin, and SBT package-dist are good plugins for creating a distribution, and we’ll show examples of all of these in future posts. It is best not to package your entire application in a single jar file, as you will not be able to take advantage of Cloud Foundry’s incremental upload capability.
2. Always include $JAVA_OPTS in your Java start commands.
When you select your application’s memory reservation through VMC, Cloud Foundry will set the JAVA_OPTS environment variable with corresponding min and max heap sizes, therefore you should include $JAVA_OPTS in your Java start commands (for example, “java $JAVA_OPTS -jar main.jar”). The start scripts generated by Maven Appassembler and Gradle Application Plugin already include JAVA_OPTS. Using JAVA_OPTS will also allow you to start your app in debug mode on local clouds, using “vmc start –debug.”
3. Use the cloudfoundry-runtime library to connect your application to Cloud Foundry services.
Ruby Applications
1. Always include a Gemfile.lock to ensure that all application dependencies are resolved by Cloud Foundry.
2. While not required, we recommend running “bundle package” before deploying your application. This will improve your application start time, as Cloud Foundry will not need to check its cache or download gems from rubygems.org.
3. Standalone Ruby applications can take advantage of Ruby Auto-Reconfiguration. To make your own connections to Cloud Foundry services, use the cf-runtime gem.
Conclusion
In this post, we used a simple example to get up and running quickly with standalone apps on Cloud Foundry. In the next installments of this four part series, we will have an in-depth look at deploying more complex standalone apps.
– Jennifer Hickey
The Cloud Foundry Team
Don’t have a Cloud Foundry account yet? Sign up for free today