Adding a deploy hook
Overview
Deploy hooks are scripts that allow you to automate actions at various points during the deployment process for your applications. This allows you to customize your deployments by, for example, installing software packages or upgrading components.
We will be looking at some simple examples in this tutorial, but for a deeper understanding please read the full reference guide.
How to use deploy hooks
To make use of deploy hooks, your application should have a file called deploy_hooks.yml.
For Rails/Rack applications this file should be present within a folder named .cloud66, which is in turn located in the root of your source code.
/.cloud66/deploy_hooks.yml
This file should be YAML formatted, and you can use a service like YAMLlint to validate it.
To create a deploy hook:
- Choose your environment - e.g. production
- Choose your hook point - e.g. first_thing
- Choose your deploy hook type - snippet, command or script.
- Select any additional hook fields you require
Understanding hook points and ordering
Hook points are used to define the point in your deployment process at which a hook should be invoked. This is obviously critical when there are tight dependencies between the components of your application (i.e. one component relies on another component being installed first), but it is also important in terms of what actions and commands are possible. For example, running tasks against a database before the database server is installed will not work!
It’s important to understand the order in which hook points will occur in the flow of deployment. The simplified deployment process below shows where each deploy hook is triggered. Hooks are marked in bold italic. Some hooks have several possible values (x
, y
, z
). Click on the hook name to see a list of available options:
Deployment process (simplified)
- Server is fired up
- Operating system and standard system components installed → first_thing
- before_agent → Cloud 66 Agent is installed → after_agent
- before_x → Database is installed → after_x
- before_y → Database replication is configured → after_y
- before_data_mount → Data is mounted → after_data_mount (GlusterFS specific)
- custom_server (runs on custom servers only)
- before_node → Node is installed → after_node
- before_nginx → NGINX is installed → after_nginx
- before_z
- Application framework is installed
- after_checkout
- after_bundle
- after_symlink
- after_z
- before_processes → processes are handled → after_processes
- last_thing
Notes
x
,y
andz
representdatabase & storage engine installation
,replication configuration
andapplication framework installation
respectively.- For the after_checkout and after_bundle hook points, the
$STACK_PATH
points to the latest code, even though after_symlink has not run yet. - Rake tasks should only be run after_symlink or later to ensure the database is available to execute the command(s)
- The source of the checkout hooks is the version of the code being deployed at all times
- The last_thing hook runs only when ALL servers reach that point
Debugging deploy hooks
Automating deploy hooks can sometimes be tricky. To avoid issues, it’s good practice to run each of your commands manually to see that they complete successfully.
If a specific command doesn’t show any output, you can use the echo $?
command after issuing your command to see its exit code. If it returns a zero, your command was successful, whereas a one means it has failed.
Using snippet deploy hooks
Below is a bare-bone example of using a snippet with the required fields. It will execute the Cloud 66 Node snippet as the first thing on all production servers.
production: # Environment
first_thing: # Hook point
- snippet: cloud66/node # Hook type
target: any # Hook fields
execute: true
You can also run multiple snippets at the same hook point:
production: # Environment
first_thing: # Hook point
- snippet: cloud66/rails # Hook type
target: any # Hook fields
execute: true
- snippet: cloud66/bower
target: any
execute: true
See the available hook points and fields for more ways to customize this.
Using command deploy hooks
The hook example below can be used to install anything from packages to fonts on your server, and you can nest different hooks for the same hook point like follows:
production: # Environment
first_thing: # Hook point
- command: apt-get install curl -y # Hook type
target: any # Hook fields
execute: true
- command: apt-get install ncdu -y # Hook type
target: any # Hook fields
execute: true
Important
When automating the installation of packages, remember to use the -y flag to answer yes to all prompts.
Running custom Rake tasks using hooks
You can use “command” hooks to run any specific or custom Rake tasks your application might need. This includes commands like db:migrate
, db:seed
and db:rollback
.
The example below can be used to run custom rake tasks during server build:
production: # Environment
last_thing: # Hook point
- command: cd $APP_PATH && bundle exec rake dev:setup # Hook type
target: rails # Hook fields
run_on: single_server
apply_during: build_only
This will run our rake task on one Rails server and only during the initial build. We run this as a last_thing
hook because if we ran it earlier the application wouldn’t exist on the server and be usable. If you need to run tasks more than once, consider using the rake task add-in.
Using existing script deploy hooks
The hook below will copy a file from your repository to your tmp folder and execute it during build.
production: # Environment
after_nginx: # Hook point
- source: /.cloud66/script.sh # Hook type
destination: /tmp/script.sh
target: any # Hook fields
execute: true
apply_during: build_only
Using inline script deploy hooks
The hook below will create an arbitrary log file in /tmp
first_thing: # Hook point
- inline: |
#!/usr/bin/env bash
echo "script called!" >> /tmp/inline_script.log
target: any
execute: true
apply_during: all
owner: root:root
Example: env vars parameter
This example shows how to use the env_vars parameter.
before_nginx:
snippet: cloud66/download
target: rails
execute: true
apply_during: build_only
run_on: all_servers
env_vars:
SOURCE_URL: "https://github.com/openresty/headers-more-nginx-module/archive/v0.33.tar.gz"
TARGET_PATH: /usr/local/build/nginx-modules/headers-more-nginx-module
UNTAR: true
What’s next?
- Get to grips with some working examples of deploy hooks to set up the exact hooks your app needs.
- Use the detailed reference guide for deploy hooks to set up the exact hooks your app needs.
- Learn how to use Manifest files to customize the components of your application
- Learn how to add custom environment variables to your application
- Learn how to use CustomConfig - a powerful tool for configuring the components of your application.