Running a Containerized Turnkey Application on Engine Yard Cloud

YouTrack is an issue tracking system developed by JetBrains. You can run it on your own servers, or pay a subscription and run it from JetBrains’s servers. It is an excellent example of a turnkey software, i.e. software that you run without modification for most of its lifetime.

In this post I will introduce you to the docker_youtrack custom Chef recipe that installs a Docker container running YouTrack on a utility instance inside an Engine Yard Cloud environment.

Even if you don’t plan to install YouTrack yourself, you can still follow along. Understanding how this recipe functions is a good starting point for writing your own Chef recipe that installs an application of your choice.

This article assumes you’re already familiar with Engine Yard Cloud and already have a running environment. If that’s not the case, please start with Getting Started with Docker on Engine Yard Cloud.

Running the Recipe

Start by grabbing a local copy of the Docker recipe repo:

git clone https://github.com/engineyard/ey-docker-recipes
cd ey-docker-recipes

We recommend running YouTrack on its own dedicated utility instance, and this is how the recipe is set up. So, you’ll need to specify the utility instance name.

Set the utility_name attribute in the cookbooks/docker_youtrack/attributes/default.rb file:

default['docker_youtrack'] = {
  'server_name' => 'youtrack.mydomain.com',
  'utility_name' => 'docker_youtrack'
}

Now edit the cookbooks/ey-custom/metadata.rb file, and enable the recipe by uncommenting (or adding) this line:

depends "docker_youtrack"

You also edit the cookbooks/ey-custom/recipes/after-main.rb file and uncomment (or add) this line:

include_recipe "docker_youtrack"

Understanding the Recipe

The recipe has two parts:

  1. Setting up the container: setup_container.rb
  2. Configuring nginx: setup_nginx.rb

You can find these in the cookbooks/docker_youtrack/recipes directory.

Setting Up the Container

The setup_container.rb script is run on the utility instance we specified previously. Open the setup_container.rb file and we’ll take a look at what each block does.

We prepare the data volumes:

['/data/youtrack/lib', '/data/youtrack/local/logs', '/data/youtrack/local/conf', '/data/youtrack/local/data', '/data/youtrack/local/backups'].each do |name|
  directory name do
    action :create
    recursive true
    owner 2000
    group 2000
    mode 0755
  end
end

Then we download the Docker image:

docker_image 'docker-youtrack' do
  repo 'dzwicker/docker-youtrack'
  action :pull
end

Finally, we run the container:

docker_container 'docker-youtrack' do
  repo 'dzwicker/docker-youtrack'
  port '9090:8080'
  volumes ['/data/youtrack/lib:/var/lib/youtrack', '/data/youtrack/local/logs:/usr/local/youtrack/logs', '/data/youtrack/local/conf:/usr/local/youtrack/conf', '/data/youtrack/local/data:/usr/local/youtrack/data', '/data/youtrack/local/backups:/usr/local/youtrack/backups']
  restart_policy 'always'
  action :run
  kill_after 10
end

Configuring nginx

On the Engine Yard V5 stack, HAProxy is installed on all app instances and listens on port 80. HAProxy then forwards HTTP requests to nginx on port 8081.

This setup_nginx.rb script creates the /etc/nginx/servers/youtrack.conf file. This configures nginx to forward HTTP requests on youtrack.mydomain.com to the Docker container. All other requests, like requests to www.mydomain.com, will still be forwarded to the application server just like before.

This diagram illustrates how HTTP requests are handled:

To implement the setup above, setup_nginx.rb is run on all application (app_master and app) instances.

Let’s go through the code block by block.

We enable nginx configuration reloading for after we create the docker_youtrack.conf nginx configuration file:

service 'nginx' do
  supports restart: true, reload: true, status: true
  action :nothing
end

We extract the Docker instance information from /etc/chef/dna.json:

instances = node.dna[:engineyard][:environment][:instances]
docker_instance = instances.find{|i| i[:name] == node[:docker_youtrack][:utility_name]}

Finally, we create (or update) the docker_youtrack.conf file:

if docker_instance && (['app_master', 'app', 'solo'].include? node.dna[:instance_role])
  template '/etc/nginx/servers/youtrack.conf' do
    owner 'deploy'
    group 'deploy'
    mode 0644
    source 'youtrack.conf.erb'
    notifies :reload, 'service[nginx]'
    variables ({
      server_name: node[:docker_youtrack][:server_name],
      docker_youtrack_hostname: docker_instance[:public_hostname]
    })
  end
end

After the nginx configuration is created or updated, an /etc/init.d/nginx reload is done to load the new configuration file.

Wrap Up

In this post, we took a look at the docker_youtrack Chef recipe that gets YouTrack running inside a Docker container on Engine Yard Cloud.

The same basic principals can be applied to any sort of turnkey application.

If you want help with this, or any other aspect of running apps on Engine Yard Cloud, don’t hesitate to ping our support team!

About Rad Batnag

Rad is the Team Lead of Engine Yard’s Asia-Pacific Support team.