Keeping up with configuration management tools is a distraction from writing beautiful code.
Let's develop a simple, elegant way to describe how our app is installed, how to run it, and what it needs.
If the focus is on our application, the description should be independent of configuration management tools (ex. Chef, Puppet), languages (Ruby, Python, JavaScript) and should work for running the app on dev laptops (Vagrant, Docker) and popular clouds (ex. AWS, OpenStack/Rackspace).
A simple app should be very simple to describe.
With [foo] installed[add link], navigate to your code repository and describe your application using the app
command:
$ app exposes http
$ app requires python --version ">=2.7.1,<3"
$ app define --start-command="python my_app.py"
Let's run an instance of our app in Docker:
$ app deploy --providers=docker
Deployed 5dff3e1 from master@d9520bba.
Browse to http://192.168.59.103:31654
RESOURCE ID ROLE TYPE ADDRESS CREATED STATUS
docker:4f44e app container 31654/tcp 7 seconds ago Up 3 seconds
Let's run an instance of our app on AWS:
$ app deploy --providers=aws --key-id=$AWS_KEY_ID --access-key=$AWS_ACCESS_KEY
Deployed cc53228 from master@d9520bba.
Browse to http://173.12.56.205
RESOURCE ID ROLE TYPE ADDRESS CREATED STATUS
aws:useast1:ffefc5c2 app server 173.12.54.18 11 seconds ago Up 2 seconds
Let's scale the Docker instance out:
$ app scale-out 5dff3e1 --count app=2 --force
Created 2 resources.
RESOURCE ID ROLE TYPE ADDRESS CREATED STATUS
docker:d7721 app app:latest 31689/tcp 7 seconds ago Up 3 seconds
docker:a7a44 lb lb:latest 31654/tcp 6 seconds ago Up 3 seconds
Modified one resource.
RESOURCE ID ROLE TYPE ADDRESS CREATED STATUS
docker:4f44e app app:latest 31686/tcp 3 minutes ago Port changed
Let's publish the definition:
$ git add blueprint.yaml
$ git commit -m "Add blueprint for my_app"
$ git push
Here's an example of how we could build a more complex app; specifying ports, environment variables, etc...
# Our web app defaults to port 8080 but falls back to any open
# port in case of conflict. Set the HTTP_PORT environment
# variable to the chosen port number and we use that below
# when defining the `start` command.
# This will create a `blueprint.yaml` file if it doesn't
# exist. We can commit the file to the repository to share
# the definition with others.
$ app exposes http --default-port 8080 --use-free-port --set-env HTTP_PORT
# Our app requires a mongo database with full text search
# enabled. We set the MongoDB URL to the MONGO_URL environment variable.
$ app requires mongodb --set-env MONGO_URL --options full_text=true
# Our app requires Python (but is not Python 3 compatible yet)
$ app requires python --version ">=2.7.1,<3"
# To run it on a debian distro, we need some packages
$ app supports debian --packages python-dev,git
# It works on OSX out of the box (no brew/macports packages
# needed)
$ app supports osx
# We can use a memcache instance if available. If so, set the
# CACHE_PORT and USE_CACHE environment variables.
$ app supports memcache --set-env CACHE_PORT=MEMCACHE_PORT,USE_CACHE=1
# This is how we start our app (use the HTTP_PORT that was
# preselected based on the `exposes` entry)
$ app define --start-command="bin/my_app START --eventlet --port HTTP_PORT"
# Here's what the yaml file looks like (edit in other tools
# if you want). Note how there is no tool-specific information
# in it
components:
app:
provides:
- application: http[8080?]
exposed: true
set_env:
- HTTP_PORT: ${settings.port}
requires:
- database: mongo
config:
- full_text: true
- runtime: python
constraints:
- version: '>=2.7.1,<3'
supports:
- cache: memcache
set_env:
- CACHE_PORT: MEMCACHE_PORT
- USE_CACHE: '1'
- compute:
from:
- debian:
packages: [python-dev, git]
- osx
commands:
start: 'bin/my_app START --eventlet --port HTTP_PORT'
In Docker it will now create two containers:
$ app deploy --providers=docker
Deployed from master@d9520bba.
Browse to http://192.168.59.103:31654
RESOURCE ID ROLE TYPE ADDRESS CREATED STATUS
docker:5f6ae mongodb container 27017/tcp 6 seconds ago Up 4 seconds
docker:4f44e app container 31654/tcp 7 seconds ago Up 3 seconds
Let's run an instance of our app on Rackspace:
$ app deploy --providers=core,rackspace --region=dfw --username=me --api-key=$API_KEY
Deployed from master@d9520bba.
Browse to http://173.12.56.205
RESOURCE ID ROLE TYPE ADDRESS CREATED STATUS
rax:dwf:d5223afa mongodb server 173.12.56.205 12 seconds ago Up 4 seconds
rax:dfw:ffefc5c2 app server 173.12.54.18 11 seconds ago Up 2 seconds
Let's manage our deployments:
$ app list deployments
ID FROM URL CREATED STATUS
5dff3e1 master@d9520bba http://192.168.59.103:31654 2 days ago Up 3 hours
cc53228 master@d9520bba http://173.12.56.205 2 days ago Up 2 days
$ app destroy 5dff3e1 --force
5dff3e1 destroyed (two resources deleted)