cf-deploy
is the tool you use to deploy your rails app to
CloudFoundry providers like Pivotal. It works with
rails 4.2 and older versions as far back as rails 3.
rake cf:deploy:production
- Deploy your rails app with one rake command
- Implement blue/green deployments
- Run asset precompiles before deploying your app
- Automate your rails deploys using jenkins, circle-ci, codeship
The functionality comes in the shape of generated rake tasks. You require this
gem in your Rakefile
and call the .rake_tasks!
setup method.
require 'cf-deploy'
CF::Deploy.rake_tasks!
By default tasks will be created for each manifest in your manifests/
folder.
If you have a staging.yml
and production.yml
you can now run the following
commands:
bundle exec rake cf:deploy:staging
bundle exec rake cf:deploy:production
You now have rake tasks that run cf push -f manifests/staging.yml
and
cf push -f manifests/production.yml
. Things start to get more exciting
when you define your environments in your Rakefile
along with their task
dependencies just like normal rake task syntax.
require 'cf-deploy'
CF::Deploy.rake_tasks! do
environment staging: 'assets:precompile'
environment production: [:clean, 'assets:precompile']
end
Now when running cf:deploy:staging
and cf:deploy:production
the prerequisite
tasks will be run first.
The next thing to talk about is route mapping. You can define a route in a an environment block like so:
require 'cf-deploy'
CF::Deploy.rake_tasks! do
environment staging: 'assets:precompile' do
route 'example.com', 'staging'
end
environment production: [:clean, 'assets:precompile'] do
route 'example.com'
route 'example.com', 'www'
route 'example.com', 'www-origin'
route 'example.com', 'admin'
end
end
As soon as an environment with routes is pushed successfully each of it's routes will be mapped to all the applications defined in the environment's manifest.
And then things get super interesting when you start talking blue/green.
Simply put, blue/green deployment allows you to deploy a new version of your app, test it on a private URL and then direct your traffic to the new version when you are ready.
You have two applications for one environment, say production. One version is called green, the other is blue. The first time you deploy your environment either green or blue can be deployed. Thereafter, any changes you want to deploy you deploy to the color that doesn't have your production domain pointed at it. You test it on a private URL and then when you're happy you flip your domain to point at that. If something then goes wrong you can then flip your domain back to the last working version.
This gem provides rake tasks for you to deploy using this methodology as well as the standard single app deployment process on a CloudFoundry provider.
Examples always help and this example is probably the most common use case. You might have a straight forward deployment for staging but use the blue/green strategy for production. Here is what your Rakefile might look like:
require 'cf-deploy'
CF::Deploy.rake_tasks! do
environment staging: 'assets:precompile'
environment production: 'assets:precompile' do
route 'example-app.io', flip: true
route 'example-app.io', 'www', flip: true
route 'example-app.io', 'www-origin', flip: true
route 'example-app.io', 'blue', blue: true
route 'example-app.io', 'green', green: true
end
end
You should also have three manifests defined:
manifests/staging.yml
manifests/production_blue.yml
manifests/production_green.yml
When you run cf:deploy:production
for the first time (assuming neither
production_blue.yml
or production_green.yml
are deployed) your blue app will
be deployed and route setup.
Running cf:deploy:production
thereafter will deploy which ever version isn't
currently deployed. Your route(s) will not be mapped automatically this time.
Nows your chance to checkout your new deployment using an alternate route. When
you're happy and want to map your route across run:
bundle exec rake cf:deploy:production:flip
You need the cf
command installed already. Grab the latest release from
the CloudFoundry CLI repo on github.
You then need to install this gem in your project's Gemfile
:
gem 'cf-deploy', '0.1.4'
You can configure some or all of your CloudFoundry details when calling
CF::Deploy.rake_tasks!
.
require 'cf-deploy'
CF::Deploy.rake_tasks! do
api 'api.run.pivotal.io'
username '[email protected]'
password 'SOMETHING'
organisation 'Made'
space 'development'
environment staging: 'assets:precompile'
environment production: 'assets:precompile' do
route 'yourwebsite.com', 'www', flip: true
end
end
All are optional. If you do not provide any you will be prompted when running the rake tasks.
Instead of defining your CloudFoundry login details in your Rakefile and committing them to your code repository you can instead provide them using ENV variables on your command line:
export CF_API=api.run.pivotal.io
export [email protected]
export CF_PASSWORD=SOMETHING
export CF_ORG=Made
export CF_SPACE=development
Now you can run any of the cf-deploy
rake tasks providing you have called
CF::Deploy.rake_tasks!
in your Rakefile
.
If you defined a staging environment in your Rakefile the following task will have been created:
bundle exec rake cf:deploy:staging
Run this to deploy out your staging environment.
Any environment you define will have a task created named cf:deploy:#{env}
.
If you have defined CloudFoundry manifest files matching manifests/*_blue.yml
and manifests/*_green.yml
you will be able to call rake cf:deploy:*
without
the _blue
or _green
. For example with production_blue.yml
and
production_green.yml
you can call the following:
bundle exec rake cf:deploy:production
Running the deploy task for an env with blue and green manifests will trigger a lookup to see which env is currently deployed. The task will then start deploying the other production color, so if green is currently deployed then blue will be deployed. If neither is currently deployed, blue will be deployed first.
Once deployed your routing will still be pointing to the previous deployment. If you run the same task again, the same environment will be deployed. That is if green was deployed, and then you run the task, blue will be deployed, if you run the task again, blue will be deployed again. This is because we work out the current deployment based on where your routes are pointing and since the deploy command for blue green environments doesn't map routes the current deployment will not change.
This isn't the case for a first time deploy. The first time you deploy your blue environment will be deployed and any defined routes will be mapped to all apps defined in your blue manifest.
In order to flip your routes from blue to green or vice-versa you need to run the following task.
bundle exec rake cf:deploy:production:flip
This will go ahead and map routes to whatever color the routes aren't mapped to and then unmap the other color. At this point your new production will be deployed and live.
Once your new production has been flipped you may want to turn off your idle application. There is a task for this too:
bundle exec rake cf:deploy:production:stop_idle
Developed and maintained by Made Tech. Key contributions:
Copyright © 2014 Made Tech Ltd. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.