Adding a deploy hook
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.
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 (
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
- Application framework is installed
- before_processes → processes are handled → after_processes
database & storage engine installation,
application framework installationrespectively.
- For the after_checkout and after_bundle hook points, the
$STACK_PATHpoints to the latest code, even though after_symlink has not run yet.
- 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
When automating the installation of packages, remember to use the -y flag to answer yes to all prompts.
Custom Rake task command
The example below can be used to run custom rake tasks during server build. If you need to run it more than once, consider using the rake task add-in.
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.
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