Содержание этой статьи было первоначально размещено Томасом Рисбергом в блоге Cloud Foundry.
Приложения JRuby Rails могут быть развернуты на CloudFoundry.com сегодня с простыми изменениями конфигурации. Приложения JRuby обычно развертываются в контейнеры сервлетов, создавая файл .war, содержащий приложение Rails. Мы сделаем то же самое для Cloud Foundry с некоторыми изменениями в конфигурации базы данных, поэтому приложение также может получить доступ к службе базы данных на CloudFoundry.com.
Изменения, необходимые для развертывания JRuby on Rails Applications в Cloud Foundry
Для запуска приложения JRuby на CloudFoundry.com необходимо выполнить две задачи. Сначала нам нужно настроить приложение для подключения к службе базы данных на CloudFoundry.com, изменив файл database.yml в каталоге конфигурации. Нам также нужно запустить эквивалент rake db: migrate при развертывании приложения для создания таблиц базы данных. Мы можем сделать это, добавив инициализатор в каталог config / initializers.
Информация, необходимая для настройки соединения с базой данных, доступна в переменной среды VCAP_SERVICES. Мы могли бы либо проанализировать эту переменную программно, либо использовать удобный гем времени исполнения Cloud Foundry (см. Использование блога Cloud Foundry Services с Ruby: Часть 2. Поддержка времени исполнения для приложений Ruby), что мы и сделаем здесь. Чтобы использовать этот драгоценный камень, нам нужно включить его в наш Gemfile:
... gem 'cf-runtime' ...
Теперь, когда мы добавили этот гем, мы можем добавить некоторые фрагменты кода в файл database.yml для доступа к информации службы баз данных для производственной среды. Ниже приведена производственная часть из файла database.yml, где мы используем базу данных MySQL:
production: adapter: mysql <% require 'cfruntime/properties' %> <% db_svc = CFRuntime::CloudApp.service_props('mysql') %> database: <%= db_svc[:database] rescue 'bookshelf_production' %> username: <%= db_svc[:username] rescue 'root' %> password: <%= db_svc[:password] rescue '' %> host: <%= db_svc[:host] rescue 'localhost' %> port: <%= db_svc[:port] rescue '3306' %>
Как видите, мы добавили оператор require для cfruntime / properties, а затем мы получаем хеш свойств службы, вызывая метод service_props, передавая тип используемого нами сервиса. Если к приложению привязана только одна служба такого типа, указывать фактическое имя службы не нужно. Вам нужно будет указать фактическое имя службы, если вы привязываете несколько приложений одного типа к своему приложению. Хэш свойств службы хранится в переменной с именем db_svc, и код извлекает соответствующие значения, которые будут использоваться для базы данных, имени пользователя, пароля, хоста и порта. У каждого из этих операторов есть пункт спасения, в котором содержатся значения, которые можно использовать, если мы не работаем в среде Cloud Foundry, и в этом случае db_svc будет равен нулю.
В качестве альтернативы производственная часть файла database.yml будет выглядеть так для PostgreSQL:
production: adapter: postgresql encoding: unicode <% require 'cfruntime/properties' %> <% db_svc = CFRuntime::CloudApp.service_props('postgresql') %> database: <%= db_svc[:database] rescue 'bookshelf_production' %> username: <%= db_svc[:username] rescue 'bookshelf' %> password: <%= db_svc[:password] rescue '' %> host: <%= db_svc[:host] rescue 'localhost' %> port: <%= db_svc[:port] rescue '5432' %>
Далее мы обратим наше внимание на создание таблиц, которые нам нужны для нашего приложения. Чтобы это произошло, нам нужно добавить следующий инициализатор в каталог config / initializers при развертывании приложения. Я назвал этот инициализатор cf_db_migrate.rb:
конфиг / Инициализаторы / cf_db_migrate.rb
require 'cfruntime/properties' # Run the equivalent of rake db:migrate on startup if CFRuntime::CloudApp.running_in_cloud? migrations = Rails.root.join('db','migrate') if migrations.directory? ActiveRecord::Migrator.migrate(migrations) end end
Мы снова используем cfruntime / properties и проверяем, что мы работаем в облаке. Затем мы проверяем, существует ли каталог db / migrate, и запускаем ли миграцию базы данных, используя файлы миграции в каталоге (ActiveRecord :: Migrator.migrate (migrations)).
Еще одно изменение, которое мы должны сделать, — это конфигурация warble. По умолчанию он не включает каталог db / migrate в сгенерированный файл war, поэтому нам нужно добавить его в конфигурацию, указав config.include = FileList [«db / migrate / *»]. Вот соответствующее содержимое файла config / warble.rb:
# Warbler web application assembly configuration file Warbler::Config.new do |config| # Application directories to be included in the webapp. config.dirs = %w(app config lib log vendor tmp) # Additional files/directories to include, above those in config.dirs config.includes = FileList["db/migrate/*"] end
Полный пример
Это предполагает, что у вас есть рабочая среда JRuby с уже установленными гемами Rails, Warbler и MySQL.
Выше мы видели, какие изменения необходимы, поэтому давайте быстро сгенерируем приложение Rails, внесем необходимые изменения и развернем приложение на CloudFoundry.com. Если вы еще не установили JRuby, лучше всего начать с JRuby .
Создайте приложение JRuby Rails
Сначала мы создаем новое приложение и создаем первый объект домена с полными лесами.
jruby -S rails new bookshelf -d mysql cd bookshelf jruby -S rails generate scaffold Book title:string category:string published:integer price:decimal{10.2} isbn:string
Затем мы удаляем сгенерированный public / index.html и модифицируем config / rout.rb, чтобы использовать «books» в качестве корня:
rm public/index.html vi config/routes.rb
Вот маршрут, который я добавил в config / rout.rb:
Bookshelf::Application.routes.draw do resources :books # You can have the root of your site routed with "root" # just remember to delete public/index.html. # root :to => 'welcome#index' root :to => 'books#index' # See how all your routes lay out with "rake routes" end
Теперь мы запустим это приложение локально, чтобы убедиться, что оно работает:
jruby -S rake db:create jruby -S rake db:migrate jruby -S rails server
Пустой список Rails сущности Book показывает, что это действительно работает. Теперь я могу добавлять новые книги на мою книжную полку.
Изменить приложение JRuby Rails для развертывания CloudFoundry
Давайте начнем с внесения следующих изменений, которые мы упомянули выше:
- добавить gem cf-runtime в Gemfile
- измените раздел «production:» файла config / database.yml, как показано выше
- добавьте файл с именем config / initializers / cf_db_migrate.rb с содержимым, показанным выше
Далее нам нужно сгенерировать конфигурационный файл Warbler, чтобы мы запустили:
jruby -S warble config
Теперь мы можем:
- измените config / warble.rb, чтобы добавить каталог db / migrate, как показано выше
Это все необходимые изменения, и теперь мы готовы упаковать и развернуть это приложение.
Упакуйте и разверните приложение JRuby Rails в CloudFoundry
Мы будем использовать Warbler для упаковки приложения в войну и утилиту командной строки CloudFoundry vmc для его развертывания.
Процесс, который мы используем, чтобы упаковать приложение в файл war, прост: связать, предварительно скомпилировать ресурсы и запустить Warbler:
jruby -S bundle install jruby -S rake assets:precompile jruby -S warble
Это создает bookshelf.war в корневом каталоге нашего приложения Rails. На данный момент есть некоторые проблемы с запуском команды vmc с JRuby, но мы работаем над исправлением этого. Тем временем мы можем переместить файл war в другой каталог, чтобы мне было легче переключаться на использование обычного «C» Ruby. Я создам каталог ‘deploy’ и сконфигурирую его для использования Ruby 1.9.2-p290 (я использую rbenv, но вы также можете использовать RVM):
mkdir deploy mv bookshelf.war deploy/. cd deploy rbenv local 1.9.2-p290 # (if you use RVM the command should be 'rvm ruby-1.9.2-p290')
Теперь мы готовы войти в CloudFoundry и развернуть наше приложение. Для этой части вам нужно установить vmc .
vmc target api.cloudfoundry.com vmc login [email protected] Password: ***** Successfully logged into [http://api.cloudfoundry.com] vmc push bookshelf Would you like to deploy from the current directory? [Yn]: Y Application Deployed URL [bookshelf.cloudfoundry.com]: mybookshelf.cloudfoundry.com Detected a Java Web Application, is this correct? [Yn]: Y Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]: 512M How many instances? [1]: 1 Bind existing services to 'bookshelf'? [yN]: N Create services to bind to 'bookshelf'? [yN]: Y 1: mongodb 2: mysql 3: postgresql 4: rabbitmq 5: redis What kind of service?: 2 Specify the name of the service [mysql-a4fd7]: mysql-books Create another? [yN]: N Would you like to save this configuration? [yN]: N Creating Application: OK Creating Service [mysql-books]: OK Binding Service [mysql-books]: OK Uploading Application: Checking for available resources: OK Processing resources: OK Packing application: OK Uploading (707K): OK Push Status: OK Staging Application 'bookshelf': OK Starting Application 'bookshelf': OK
Команды vmc выделены выше. Большинство значений по умолчанию были приняты, за исключением URL-адреса и необходимости создания службы. Я использовал URL «mybookshelf.cloudfoundry.com» вместо стандартного, чтобы избежать конфликта с существующими приложениями на книжной полке. Я ответил «Y» на вопрос о создании нового сервиса, выбрал (2) mysql и назвал его «mysql-books».
Теперь мы должны увидеть запущенное приложение:
vmc apps
+-------------+----+---------+---------------------------------+---------------+
| Application | # | Health | URLS | Services |
+-------------+----+---------+---------------------------------+---------------+
| bookshelf | 1 | RUNNING | mybookshelf.cloudfoundry.com | mysql-books |
+-------------+----+---------+---------------------------------+---------------+
Теперь мы можем ввести «http://mybookshelf.cloudfoundry.com/» и увидеть, как приложение «Книжная полка» оживает и добавить несколько книг.
Вы можете просмотреть и загрузить весь источник, использованный для этого примера, на cloudfoundry-samples / jruby-rails-bookshelf или, если вы просто хотите увидеть изменения, необходимые для развертывания в Cloud Foundry, посмотреть на этот коммит .
Вывод
Мы показали, что можно развернуть простое приложение JRuby on Rails в cloudfoundry и использовать службу MySQL в качестве резервного хранилища данных. Все, что требуется, это некоторые изменения в конфигурации приложений базы данных.
В следующем посте мы рассмотрим аналогичные изменения, которые мы должны сделать для приложения JRuby Sinatra, которое использует DataMapper для сохранения.