We publish Ruby, Python, Node.js, Perl and Java web applications in Azure Cloud Services

    imageIn this article, we will look at how to deploy web applications written using various technologies in the Azure Cloud Services cloud. Namely, it will be Ruby, Python, Node.js, Perl and, with some caveats, also Java and Railo (ColdFusion). As an example of a Ruby application, we will use Redmine running on Ruby on Rails, Python will use the Lightning Fast Shop running on Django, in Node.js we will use a small project using express.js, we will set an empty Mojolicious project on Perl. The purpose of this article is not a tour of all these web technologies, but only to show a convenient and universal way to publish to the Azure cloud. So there will be no Ruby, Python or Perl code in it. But there will be many screenshots, shell scripts and instructions for packaging and deploying applications.


    So, what is Azure Cloud Services and what does it eat with:

    Unfortunately, the abundance of marketing materials on the network does not reveal this topic well and creates a lot of noise. And we will try to discuss this issue in a human language that is understandable for simple web developers. First, what’s important to understand for a developer who wants to learn how to use Azure Cloud Services is that this service is actually a virtual machine factory. How this is implemented is not technically important, the main thing that interests us is that the Azure infrastructure can quickly and automatically provide us with a number of identical virtual machines with a certain amount of resources on which our website or other application can run.

    In the Azure system, all these virtual machines are approximately the same and can be Windows Server 2008, 2008 R2, and 2012. Apparently, this is done because creating such virtual machines is quite cheap for the system and these machines themselves do not consume a lot of resources plus the same virtual machines are easy to manage. Although I personally do not know the internal structure of Azure Cloud Services and this is just an assumption. The main difference from VPS hosting is that we do not need to configure these virtual machines. The Azure system will deploy the virtual machine itself and install our application on it when it is needed. This allows you to dynamically create and delete virtual machines as needed, automatically and without our participation. In order to implement this technology, our application must be specially written and packaged,

    Why is it profitable for us: First of all, it is saving resources, and therefore our money (it depends, of course, on the price of the service). Sites do not always need the maximum amount of resources. If buying VPS or Dedicated hosting we are forced to take the maximum configuration that we may need, then in the case of Azure Cloud Services we can only pay for the virtual machines that we need at the moment. When the load on the resource increases, the Azure system will automatically allocate new virtual machines to serve our site. When the load drops, the virtual machines will return to the system and we will not pay for them.

    Why does the hoster need this (in this case Microsoft): The reason is the same - saving resources. Typically, different sites and services do not need the maximum amount of resources at the same time. This means that this allows the provider to host more websites on fewer physical resources. The same savings as in the case of shared hosting - not everyone needs peak load at the same time. Therefore, shared hosting is usually cheaper.

    And now the unpleasant moment - this complicates the development of the application and ties us to the platform. Rather, it does not complicate, but slightly changes the approach, makes it not so familiar. After all, developers are usually used to the fact that there is some server to which you can open an SSH session or RDP, where you can run various commands to configure the environment they need. Despite the fact that, theoretically, in Azure Cloud Services, you can also open RDP to a virtual machine, it’s a little useless, except for debugging purposes. After all, after 5 minutes, the system can spawn a dozen more of these "servers" that will not be configured by you manually. And then completely delete your configured server without warning.

    Solving the server configuration problem is quite simple - you need to pack our application before publishing so that the system itself knows how to configure it, what actions need to be performed on the server for our application to work. In addition to the application itself, this package should also include all its dependencies, which may be needed on the server to run and configure it. And most importantly, there should be scripts that can configure a clean new virtual machine for our application. The Azure system will deploy this package and execute scripts every time a new virtual machine goes live.

    В этой статье мы будем использовать такое решение, чтобы сохранить максимальную независимость от платформы. Ведь платформозависимость и невозможность затем переехать на другой сервис – один из главных факторов тормозящих переход на облачные сервисы на данный момент. Не случайно мы выбрали общеизвестные приложения для примеров и технологии с открытым кодом – способы настройки этих приложений на других платформах общеизвестны. А значит при необходимости можно переносить приложение с одной платформы на другую. Итак, достаточно теории, перейдем к практике. Сейчас будем рассматривать пример использования по каждой технологии по очереди. Так как для каждой технологии будет много одинаковых действий, чтобы сократить статью я не буду повторяться, поэтому я советую читать весь текст подряд, даже если данную конкретную технологию вы использовать не собираетесь.

    Ruby


    Let's start with Ruby and look at all the key points with her example, so this chapter will be the longest. If you haven’t worked with Ruby, it’s okay. We will practically not use specific commands, and the steps to configure all platforms are the same. First, we need a Windows workstation. We will use Helicon Zooto run Ruby applications on IIS both on the workstation and on the Azure system. Not only will it be easier to configure the runtime for our application, such a configuration in Azure will create a much better and more reliable solution in terms of performance than starting a Ruby process with an integrated server on port 80, as is often done in other instructions. Plus, launching the application in IIS will also allow us to incorporate other technologies and capabilities of IIS into the application, add sections on ASP.NET and other languages ​​listed in this article to the site, configure SSL and URL Rewriting, make full use of multicore machines, ship static data using IIS itself, which will also significantly save resources, and much more.

    If you have already worked with Ruby, then it is possible that your workstation already has an installed and configured version of Ruby, with installed gems, etc. This is all good, but how can I migrate it to Azure Cloud Services? Using Helicon Zoo packages, we can pack all the application dependencies into one archive, which allows us to easily transfer it to other servers, including Azure Cloud Services. So for the sake of fidelity, we will install the latest version of Ruby from the Helicon Zoo repository, regardless of whether there is another Ruby on your machine.

    So, follow the link and install the Microsoft Web Platform Installer . Run it and press Options and in the window that opens add Helicon Zoo feed: http://www.helicontech.com/zoo/feed.xml

    At the workstation, I also advise you to select IIS Express as the server, as it will be easier to work with for tests and require less settings.



    Next, you need to install the Windows Azure SDK and the easiest way to do this is using the same Web Platform Installer. Type “Azure SDK 2.1” into the search, or simply click on this link . If at the time of reading the article the SDK version is out of date and the link will not work, just find the newer one in the list:



    The Azure SDK includes a set of utilities for creating and testing packages for Windows Azure Cloud Services, which we will need. We will use command line utilities and we will not use Visual Studio and other tools for automatic publishing of sites, as I tried to minimize the amount of “magic” in the article. Especially since we publish an application in Ruby, it is doubtful that Visual Studio will be your development tool. Therefore, I suggest installing the base Azure SDK, and not the Azure SDK for Ruby. The latter already includes some Ruby distribution and a set of configurations that may not be bad, but definitely not the ones that will be used in this article. If you’re still used to using Visual Studio to create Azure packages, then it’s easy for you to manually create the package you need,

    Now let's create a Ruby application on our workstation. If you already have a ready-made Ruby Rack application, then you need to run the Web Platform Installer, and install the “Ruby project” from the Zoo -> Templates section. Next, follow the instructions on the invitation page of the resulting template site.



    However, everyone seems to be tired of installing “Hello World” applications, and writing more advanced code is beyond the scope of this article, so we will just put Redmine as a fairly complex and well-known open-source Ruby on Rails application. To do this, open the same Web Platform Installer, go to Zoo -> Applications and install Redmine. When the installation is complete, the application deployment process starts, which simply automatically performs the steps described in this article(English) in the Manual installation section.



    At the same time, no preliminary installation of Ruby, Dev Kit, gems, or even IIS Express itself is required - the Web Platform Installer and Helicon Zoo will take care of everything. All required packages will be downloaded from the Internet and installed on your workstation. After all components are installed, you should see the first page of Redmine. Of course, in a good way, you still need to configure the correct database, but for our test, the default SQLite is already quite enough.

    Pay attention to the file structure of the resulting site (you may need to press F5 in WebMatrix to update the look of the folders):



    The GEM_HOME folder contains all the gems that our application depends on. It is from there that they will be loaded during operation. The deploy_done.rb file is the deploy.rb script that we observed in the previous step, on the page with the message “Application deployment in progress”. Upon completion of its execution, Helicon Zoo renamed this file to deploy_done.rb to prevent restarting unnecessarily. If you need to start the process in a new way, just rename this file back to deploy.rb and from the next request to the server the script will be launched again. This script contains standard commands for finding and installing missing dependencies, creating, if necessary, database migrations, etc. This is one of the ways how to execute commands in the context of the application, more about which can be found indocumentation Zoo then Helicon (Eng.) . Another way is to start Helicon Zoo Manager (for IIS Express) from Start -> Programs -> Helicon -> Zoo, and there, by choosing our application, you can click on the Start Web console or Start IDE.



    The Web console allows you to execute commands in the context of the application and on behalf of the user of this application (Application pool user in the case of IIS and interactive user in the case of IIS Express), both on the local machine and on the remote server. The Start IDE button allows you to start the program (by default it will be the cmd.exe command line) in a pre-configured environment of variables and paths for the selected web application. It will also allow the execution of commands that will be applied to our application, and not globally to the system. Most modern IDEs, such as Aptana or PyCharm, have a built-in command line, correctly recognize these variables and allow working with local application folders more or less in isolation and execute commands directly from the environment. So I recommend that you configure the start of your favorite IDE using the Start IDE button and execute all the commands from there. You can also export environment variables to a .cmd file by clicking on Tools -> Export application environment. This file can then be called before executing other script commands intended for the application and it will set the required paths and environment variables. This is convenient if, for example, you need to apply commands to a timer application from Windows Scheduler.

    Why is it so important to use these tools? Because they allow you to pack all the dependencies inside the application. After all, our application will be sent to work on Azure Cloud Services and we need to have all the necessary dependencies with us. Of course, we could run the Ruby command 'bundle install' to download from the Internet and install all the dependencies every time a new Cloud Services node goes into operation. However, then our application will also depend on the operation of the rubygems.org service and other Internet resources, the 100% availability of which is in question. In addition, there is always the possibility that we will forget to specify the exact version of any gem from secondary dependencies and our application will suddenly stop working with the release of a new, incompatible version of gem, although we did not seem to change anything. Multiply all these probabilities, and you will not get such an attractive uptime. So, we need to minimize the number of external dependencies, so that whenever possible when installing from the Internet, nothing will swing - then all new virtual machines will be exact copies of each other.

    And there is one subtle point - a habit. If, for example, Java programmers are used to the fact that all dependencies should be packaged with the application for granted, then Ruby programmers are more used to configuring the server with their hands and at their own discretion. So working with Helicon Zoo will require some discipline, namely: you cannot start the console or IDE to work with the application, even on your workstation, without first configuring the path to the application. You can do this either by running the console and the IDE from Helicon Zoo Manager, or by executing the file exported from the application environment.cmd before running other commands. It also follows that you can not install gems and other modules globally. Using these rules, you can get an easily portable application that is convenient to transfer from one server to another.

    Since we installed Redmine directly from the Helicon Zoo repository, all dependencies were installed into the application automatically. Now, to transfer our Redmine to another server, we only need to install Helicon Zoo -> Ruby Hosting Package on this server and transfer the folder with the site itself. Ruby Hosting Package already includes Ruby of different versions, Dev kit, Helicon Zoo Module and all other dependencies that may come in handy on the server. Instead of installing the Ruby Hosting Package, you can basically only install the required packages from the Helicon Zoo repository separately to save space. However, there is a greater likelihood of missing something, and Ruby distributions do not take up much space to save.

    On the server, we will not download Ruby and Helicon Zoo packages from the Internet so as not to depend on the availability of distributions and servers. For this, there is also a way to pack everything once, and then install it from the archive. We use the Web Platform Installer and the command line utility WebpiCMD.exe . You can usually find it in the Web Platform Installer installation folder: C: \ Program Files \ Microsoft \ Web Platform Installer. This utility can package products from the Web Platform Installer for subsequent installation without an Internet connection.

    First, start the console with administrative rights by right-clicking on it and selecting 'Run as administrator':



    This is necessary so that a new console window does not open when starting WebpiCMD.exe, otherwise it will be difficult to read the output of the command. We will save installation packages in the directory of the site with Redmine in the 'offline-package' folder. Because I installed Redmine under IIS Express, then my site is located in the folder 'C: \ Users \ Slov \ Documents \ My Web Sites \ redmine222 '. In your case, the folder name will be different, so fix this in the following command and execute in the console:

    mkdir "C:\Users\Slov\Documents\My Web Sites\redmine222\offline-package"
    WebpiCmd.exe /offline /Products:RubyHostingPackage /Path:"C:\Users\Slov\Documents\My Web Sites\redmine222\offline-package" /Feeds:http://www.helicontech.com/zoo/feed.xml


    As can be seen from the command, we indicate the product that must be saved for offline installation. At the same time, WebpiCmd.exe will save all its possible dependencies, bits, etc. The path to the folder where to save the packages and the URL of the Helicon Zoo repository is redirected to the command, where all these packages come from. The whole process may take some time. Remember that many shell commands do not like spaces in the path, so don’t forget quotes. This command will save the RubyHostingPackage product and all its possible dependencies to the 'offline-package' folder inside our website. You can then use the contents of this folder to install the Ruby Hosting Package on another machine. At the time of writing, Helicon Zoo includes seven hosting packages and their names are as follows:

    CFMLHostingPackage    CFML Hosting Package
    JavaHostingPackage    Java Hosting Package
    RubyHostingPackage    Ruby Hosting Package
    NodejsHostingPackage  Node.js Hosting Package
    PerlHostingPackage    Perl Hosting Package
    PHPHostingPackage     PHP Hosting Package
    PythonHostingPackage  Python Hosting Package

    You can read more about offline installation in English at this link . You can see the internal names of all available products using the / List key of the WebpiCmd.exe command. The original English documentation for the WebpiCMD.exe utility is here .

    If you look at the structure of the resulting 'offline-package' folder, you will see in the bin folder that WebpiCMD.exe, by the way, has already included a working copy of itself in the package. We will call it on the Azure Cloud Services virtual machine to install the necessary dependencies back from the package.



    Before you pack our site for Azure, you need to add a script to it that will install all the dependencies on the virtual machine. According to Azure’s rules, this script should be located in the bin directory under the root of the site itself. Call this file startup.cmd. Here is its contents:

    [bin \ startup.cmd]
    echo Starting installation...
    rem Дать права на чтение и запись папке куда распаковано приложение
    icacls "%RoleRoot%\approot" /grant "Everyone":F /T
    rem Локальная папка AppData с правами на запись нужна для работы Web Platform Installer
    rem Создадим эту папку и ключ реестра на нее указывающий
    md "%RoleRoot%\appdata"
    reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
        /v "Local AppData" /t REG_EXPAND_SZ /d "%RoleRoot%\appdata" /f
    rem Перейдем в папку с WebpiCmd.exe
    pushd "%RoleRoot%\approot\offline-package\bin"
    rem Вызов команды WebpiCmd.exe для установки продукта из папки offline-package
    rem Обратите внимание на имя продукта - RubyHostingPackage, а также логи в install.txt и install-error.txt
    WebpiCmd.exe /install /Products:RubyHostingPackage /XML:%RoleRoot%\approot\offline-package\feeds\latest\webproductlist.xml ^
                 /Feeds:%RoleRoot%\approot\offline-package\feeds\latest\supplementalfeeds\feed.xml ^
    			 /AcceptEula >%RoleRoot%\approot\public\install.txt 2>%RoleRoot%\approot\public\install-error.txt
    popd
    rem Вернуть старое значение ключу реестра с AppData
    reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
        /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f
    rem Тут можно выполнить другие действия, например удалить временные файлы.
    echo Completed installation.
    

    The variable% RoleRoot% will indicate where our role is installed, and the% RoleRoot% \ approot folder will accordingly be the root folder of the site. The main line in this file is a call to WebpiCmd.exe. Pay attention to the redirection of the output of the installation logs to the install.txt file, and the STDERR output will be in the install-error.txt file - both to the public folder of the root of the resulting site. You can then request these files by URL to read possible installation errors if the experience fails the first time. The first line sets the write permissions to the folder with the site - these rights are needed by Redmine itself to work, because Ruby applications are often written to the application folder.

    Now is the time to pack the site for Azure Cloud Services. My site is located in the folder "C: \ Users \ Slov \ Documents \ My Web Sites \ redmine222". We’ll go to the folder in the folder above our site — I will have the folder “C: \ Users \ Slov \ Documents \ My Web Sites \”. Here we will need to create three files: a service configuration file * .cscfg, a file with parameters for creating a * .csdef package, and a cmd script file that will be conveniently packaged. Here are these files with some comments:

    [remine222.csdef]

    For some reason, the role name and the name of the folder where it is located must match.

    [redmine222.cloud.cscfg]

    Descriptions and formats of these files can be found on the Internet and in the documentation for Windows Azure itself, so omit the details.

    [redmine222.pack.cmd]
    @echo off
    set WINDOWS_AZURE_SDK_PATH="C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.1"
    call %WINDOWS_AZURE_SDK_PATH%\bin\setenv.cmd
    pushd %~dp0
    if "%ServiceHostingSDKInstallPath%" == "" (
        echo Can't see the ServiceHostingSDKInstallPath environment variable. Please run from a Windows Azure SDK command-line (run Program Files\Windows Azure SDK\^\bin\setenv.cmd^).
        GOTO :eof
    )
    rem Тут можно удалить временные файлы, остановить IIS и т.п.
    rem iisreset /stop
    rem Переименовать deploy_done.rb в deploy.rb чтобы запустить процесс деплоя по новой
    ren redmine222\deploy_done.rb deploy.rb
    rem Эта команда создает пакет для Windows Azure
    cspack redmine222.csdef /out:redmine222.cspkg
    popd

    Pay attention to the line
    ren redmine222\deploy_done.rb deploy.rb

    This command renames the deploy_done.rb file to deploy.rb, which will restart the deployment script in Helicon Zoo on the first request to the deployed application. If we packed all the modules correctly and we do not need to migrate the database, then this step is optional and can save time. However, the probability that everything will be correctly packed the first time is not very high, so for the first attempts, I recommend leaving this line.

    Another recommendation would be to edit the web.config file of the root of the site and add such a line to the section:

    This line enables the generation of detailed messages about the 500th error with external requests to IIS. Without this line, if something breaks in the application, you will not see the error text, but only the dry message 'Server error'. To work in production mode, this line is better to remove, but for the first start it can come in handy.

    At this link you can find examples of the files described above in accordance with the folder structure of the project - to make it clear what to put.

    All files are ready. Now, before calling redmine222.pack.cmd, you need to stop IIS or IIS Express on the workstation to unlock the application files. Then call redmine222.pack.cmd from our administrative console. The packaging process will take some time and as a result we will get the redmine222.cspkg file, which is actually a ZIP archive with all the necessary packages. The size of this file I got 138 megabytes, which is a lot, because it includes versions of Ruby 1.8, 1.9, two versions of Ruby DevKit, Helicon Zoo Module, Microsoft URL Rewrite, Redmine itself and all the gems required for its operation. But this archive includes all the dependencies and we don’t have to download anything from the Internet, and the archive itself will be transferred inside the Azure network, which, I dare to hope, is much faster.

    Now let's go to the Windows Azure Management Portal. You need to create a new Cloud Service and select the URL for it:



    Then you need to select "New staging deployment":



    Select our files with Redmine from the local folder. You need to specify the flag “Deploy even if role contain a single instance”, because in the redmine222.csdef file we specified to use one instance of the role, which is enough for tests, although in real conditions you will most likely need to increase this number.



    After that, the process of downloading the package to Azure, creating a new virtual machine, deploying our package with the application on this virtual machine, and executing installation scripts will begin. The process is quite lengthy, it takes me 20 minutes - no less. When all installation processes are complete, click on the Site URL link.



    Вы должны увидеть страницу Applcation deployment из Helicon Zoo, которая затем обновится на домашнюю страницу Redmine:



    Чтобы затем ваш веб сайт стал виден пользователям под более приемлемым доменным именем, вам нужно в настройках вашего домена у регистратора указать либо CNAME запись на доменное имя внутри .cloudapp.net (предпочтительно) или указать 'A'-record вашего домена на публичный IP адрес вашего Azure-приложения. Сам же Microsoft не занимается предоставлением услуг по регистрации доменов.

    Python



    In this chapter, we will look at how to manually install an application that is not part of the Helicon Zoo repository. To do this, we will use the open source Lightning Fast Shop (LFS) application written in Python using Django. The steps for publishing an application to the Azure Cloud Service will be almost identical to the previous chapter, but the steps for deploying the application on a workstation will be different.

    So, we install the Microsoft Web Platform Installer , Helicon Zoo feed and the Windows Azure SDK , as in the previous chapter, if any of this is not yet installed. Launch the Web Platform Installer and install Zoo -> Templates -> Python project on IIS Express.



    WebMatrix starts up and a new site opens:



    We just installed a template project for Python. Virtualenv is already configured in this project, which will be used to install all the modules and dependencies inside the site. To start your Python project, you can go further according to the instructions on the Python project invitation page. Just do not forget to start the console or IDE (for example PyCharm ) using Helicon Zoo Manager, so that the console starts with the pre-configured virtualenv, otherwise the commands will not find the path to our application.

    Lightning Fast Shop is a rather large and moody installation program, so I ask you to step by step repeat the following instructions for installing it manually on IIS and Helicon Zoo. I will not give too detailed explanations of what is happening, because what is happening is related to the features of the LFS project, and not to Helicon Zoo or Azure. Setting up another project may follow a different scenario. If unsuccessful, try starting with smaller and simpler projects, following the instructions from the Python project. I chose the LFS project simply to show that not only “Hello World” can be launched on Azure Cloud Services.
    1. Download the LFS distribution from the official site . I chose version 0.7.7. You must download the installer version, which has a file name like django-lfs-installer-0.7.7.tar.gz.
      The archive will contain the folder 'lfs-installer' - unzip its contents to the root of the site with our Python project (in my case, this is the folder C: \ Users \ Slov \ Documents \ My Web Sites \ ZooPythonProject2).
      Launch Helicon Zoo Manager, select the desired site with the project and click on the Start IDE to launch the configured console.
      In the console, enter:
      python bootstrap.py
      Then
      bin\buildout –v
      Then edit the lfs_project \ settings.py file and replace the DATABASES section with the following text for use in an SQLite project:
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
              'NAME': os.path.join(DIRNAME, 'sqlite3.bd'),                      # Or path to database file if using sqlite3.
              'USER': '',                      # Not used with sqlite3.
              'PASSWORD': '',                  # Not used with sqlite3.
              'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
              'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
          }
      }
      Then enter the following commands in the console:
      bin\django syncdb
      bin\django lfs_init
      bin\django collectstatic
      If everything worked without errors, now you can run the Django test server to test the operation of the LFS project separately from the IIS web server. Run in the console:
      bin/django runserver
      And then open in your browser http: // localhost: 8080 /

      Now, to start the project on IIS via Helicon Zoo, you need to set PYTHONPATH in the web.config file . At LFS, it is long and includes many egg packages. You can find it in the bin \ django_script.py file:
      #!"C:\Users\Slov\Documents\My Web Sites\ZooPythonProject2\venv\Scripts\python.exe"
      import sys
      sys.path[0:0] = [
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_lfs-0.7.6-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\gunicorn-18.0-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\djangorecipe-1.1.2-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django-1.3.1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\zc.recipe.egg-2.0.1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\zc.buildout-2.2.1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\south-0.7.3-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\pillow-1.7.5-py2.7-win32.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\lfs_order_numbers-1.0b1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\lfs_contact-1.0-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_tagging-0.3.1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_reviews-0.2.1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_postal-0.9-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_portlets-1.1.1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_paypal-0.1.2-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_pagination-1.0.7-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_lfstheme-0.7.3-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_compressor-1.1.1-py2.7.egg',
        'c:\\users\\slov\\documents\\my web sites\\zoopythonproject2\\venv\\lib\\site-packages',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_piston-0.2.3-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_countries-1.5-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\django_appconf-0.6-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\eggs\\six-1.4.1-py2.7.egg',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\parts\\django',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\parts',
        'c:\\users\\slov\\docume~1\\mywebs~1\\zoopyt~1\\lfs_project',
        ]
      import djangorecipe.manage
      if __name__ == '__main__':
          sys.exit(djangorecipe.manage.main('lfs_project.settings'))

      As you can see there are absolute paths, which does not suit us, because the project will be transferred to Azure. To set PYTHONPATH via web.config, these paths need to be redone in such a slightly strange format. Here is a snippet of my web.config:

      You can copy to your web.config, however if you are setting up a version other than 0.7.7, then your PYTHONPATH may be different.

      Also set the DJANGO_SETTINGS_MODULE variable in web.config:

      Now the contents of the folder '\ lfs_project \ sitestatic' need to be moved to the folder '\ static' in the root of the site.

      Everything, the project is ready to run on IIS. Click on the link in WebMatrix and you should see the LFS homepage.

      The folder structure as a result was as follows:



      Next, we will prepare a package for Azure Cloud Services. Launch Helicon Zoo Manager, select the desired site and click the Start IDE to launch the console. Web console will not work here, because she will not have enough rights. Run the following commands there:

      mkdir offline-package
      WebpiCmd.exe /offline /Products:PythonHostingPackage /Path:"offline-package" /Feeds:http://www.helicontech.com/zoo/feed.xml

      This will save the Python Hosting Package in the offline-package directory inside the site.

      Then create three files for Azure Cloud Services in the 'My Documents \ My Web Sites' folder, as in the previous chapter. I highlighted in bold those lines that are different from the previous ones in these files:

      [LFS.Cloud.cscfg]


      [LFS.csdef]


      [LFS.pack.cmd]
      @echo off
      set WINDOWS_AZURE_SDK_PATH="C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.1"
      call %WINDOWS_AZURE_SDK_PATH%\bin\setenv.cmd
      pushd %~dp0
      if "%ServiceHostingSDKInstallPath%" == "" (
          echo Can't see the ServiceHostingSDKInstallPath environment variable. Please run from a Windows Azure SDK command-line (run Program Files\Windows Azure SDK\^\bin\setenv.cmd^).
          GOTO :eof
      )
      rem Тут можно удалить временные файлы, остановить IIS и т.п.
      rem iisreset /stop
      del /s /q *.log *.pyc *.pyo
      rem Эта команда создает пакет для Windows Azure
      cspack lfs.csdef /out:lfs.cspkg
      popd

      And it remains to create the file \ bin \ startup.cmd in the root of the site:
      echo Starting installation...
      rem Дать права на чтение и запись папке куда распаковано приложение
      icacls "%RoleRoot%\approot" /grant "Everyone":F /T
      rem Локальная папка AppData с правами на запись нужна для работы Web Platform Installer
      rem Создадим эту папку и ключ реестра на нее указывающий
      md "%RoleRoot%\appdata"
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d "%RoleRoot%\appdata" /f
      rem Перейдем в папку с WebpiCmd.exe
      pushd "%RoleRoot%\approot\offline-package\bin"
      rem Вызов команды WebpiCmd.exe для установки продукта из папки offline-package
      rem Обратите внимание на имя продукта - PythonHostingPackage, а также логи в install.txt и install-error.txt
      WebpiCmd.exe /install /Products:PythonHostingPackage /XML:%RoleRoot%\approot\offline-package\feeds\latest\webproductlist.xml ^
                   /Feeds:%RoleRoot%\approot\offline-package\feeds\latest\supplementalfeeds\feed.xml /AcceptEula  ^
                   >%RoleRoot%\approot\static\install.txt 2>%RoleRoot%\approot\static\install-error.txt
      popd
      rem Вернуть старое значение ключу реестра с AppData
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f
      rem Тут можно выполнить другие действия, например удалить временные файлы.
      echo Completed installation.
      

      In this archive you will find an example of the files described above.

      Run LFS.pack.cmd. The resulting LFS.cspkg file takes 70mb for me.

      Delete the old Staging Environment from the Azure Portal and create a new one. We will transfer the files as in the previous chapter and wait for the launch.



      When the line “Not all instances are ready” disappears, you can open the link where we should see the working Lightning Fast Shop in Azure Cloud Services.



      Node.js


      Now the turn of Node.js. So, launch the Microsoft Web Platform Installer and install Zoo -> Templates -> Node.js project . All dependencies will be installed automatically.



      After launching, the project will be deployed into a fully finished Model-View-Route application built on the basis of express.js, sqlite3, persist.js and Twitter Bootstrap. In this template, for example, there will already be a simple blog and an administrative panel for it. Such an application can be a good starting point for creating your own website. If you already have a ready-made Node.js website, then you obviously know the purpose of all the files specified in the template project. Just overwrite your files on top, leaving web.config intact and your application should work.



      We will install this simple blog on Azure Cloud Services. As in the previous chapters, launch Helicon Zoo Manager and click on the Start IDE or Start web console. In the console, type:

      mkdir offline-package
      WebpiCmd.exe /offline /Products:NodejsHostingPackage /Path:"offline-package" /Feeds:http://www.helicontech.com/zoo/feed.xml

      Next, create the file bin \ startup.cmd :

      [bin \ startup.cmd]
      echo Starting installation...
      rem Дать права на чтение и запись папке куда распаковано приложение
      icacls "%RoleRoot%\approot" /grant "Everyone":F /T
      rem Локальная папка AppData с правами на запись нужна для работы Web Platform Installer
      rem Создадим эту папку и ключ реестра на нее указывающий
      md "%RoleRoot%\appdata"
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d "%RoleRoot%\appdata" /f
      rem Перейдем в папку с WebpiCmd.exe
      pushd "%RoleRoot%\approot\offline-package\bin"
      rem Вызов команды WebpiCmd.exe для установки продукта из папки offline-package
      rem Обратите внимание на имя продукта – NodejsHostingPackage, а также логи в install.txt и install-error.txt
      WebpiCmd.exe /install /Products:NodejsHostingPackage /XML:%RoleRoot%\approot\offline-package\feeds\latest\webproductlist.xml ^
                   /Feeds:%RoleRoot%\approot\offline-package\feeds\latest\supplementalfeeds\feed.xml ^
                   /AcceptEula  >%RoleRoot%\approot\public\install.txt 2>%RoleRoot%\approot\public\install-error.txt
      popd
      rem Вернуть старое значение ключу реестра с AppData
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f
      rem Тут можно выполнить другие действия, например удалить временные файлы.
      echo Completed installation.

      And then three files in the “My Web Sites” directory:

      [Node.js.Cloud.cscfg]


      [Node.js.csdef]


      [Node.js.pack.cmd]
      @echo off
      set WINDOWS_AZURE_SDK_PATH="C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.1"
      call %WINDOWS_AZURE_SDK_PATH%\bin\setenv.cmd
      pushd %~dp0
      if "%ServiceHostingSDKInstallPath%" == "" (
          echo Can't see the ServiceHostingSDKInstallPath environment variable. Please run from a Windows Azure SDK command-line (run Program Files\Windows Azure SDK\^\bin\setenv.cmd^).
          GOTO :eof
      )
      rem Тут можно удалить временные файлы, остановить IIS и т.п.
      rem iisreset /stop
      rem Эта команда создает пакет для Windows Azure
      cspack Node.js.csdef /out:Node.js.cspkg
      popd

      As before, the differences are in bold.

      We execute Node.js.pack.cmd, as a result we get a Node.js.cspkg file about 41mb in size. Here is a link to the archive with sample files above: https://dl.dropboxusercontent.com/u/7840290/habrahabr/Node.js.zip

      Now we will publish the packages in Azure Cloud Services as in the previous chapters. The whole process takes 5-10 minutes, which is much faster than, for example, in the case of Ruby.

      Perl


      This time, we will be putting the “Hello World” project on Mojolitious. Unfortunately, nothing more spectacular for Perl was at hand. Launch the Microsoft Web Platform Installer and install Zoo -> Templates -> Perl project .



      After installation, the "Welcome to universal Perl template powered by Helicon Zoo" page will open, click on the "open web console" link on this page and type the following command there:
      cpanm Mojolicious

      Now create an app.pl file with this content:

      [app.pl]
      use Mojolicious::Lite;
      get '/' => sub { shift->render(text => 'Hello from Mojolicious!') };
      app->start;

      Clicking “refresh” in the browser will see the message “Hello from Mojolicious!”. Not so hot as beautiful, but it proves the concept.

      Now, as in the previous chapters, we execute from the console:

      mkdir offline-package
      WebpiCmd.exe /offline /Products:PerlHostingPackage /Path:"offline-package" /Feeds:http://www.helicontech.com/zoo/feed.xml

      Add the script bin \ startup.cmd:

      [bin \ startup.cmd]
      echo Starting installation...
      rem Дать права на чтение и запись папке куда распаковано приложение
      icacls "%RoleRoot%\approot" /grant "Everyone":F /T
      rem Локальная папка AppData с правами на запись нужна для работы Web Platform Installer
      rem Создадим эту папку и ключ реестра на нее указывающий
      md "%RoleRoot%\appdata"
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d "%RoleRoot%\appdata" /f
      rem Перейдем в папку с WebpiCmd.exe
      pushd "%RoleRoot%\approot\offline-package\bin"
      rem Вызов команды WebpiCmd.exe для установки продукта из папки offline-package
      rem Обратите внимание на имя продукта – PerlHostingPackage, а также логи в install.txt и install-error.txt
      WebpiCmd.exe /install /Products:PerlHostingPackage /XML:%RoleRoot%\approot\offline-package\feeds\latest\webproductlist.xml ^
                   /Feeds:%RoleRoot%\approot\offline-package\feeds\latest\supplementalfeeds\feed.xml ^
                   /AcceptEula  >%RoleRoot%\approot\public\install.txt 2>%RoleRoot%\approot\public\install-error.txt
      popd
      rem Вернуть старое значение ключу реестра с AppData
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f
      rem Тут можно выполнить другие действия, например удалить временные файлы.
      echo Completed installation.

      And create the files in the “My Web Sites” folder (it is assumed that the site is in the “My Web Sites \ Perl project” folder):

      [Perl.Cloud.cscfg]


      [Perl.csdef]


      [Perl.pack.cmd]
      @echo off
      set WINDOWS_AZURE_SDK_PATH="C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.1"
      call %WINDOWS_AZURE_SDK_PATH%\bin\setenv.cmd
      pushd %~dp0
      if "%ServiceHostingSDKInstallPath%" == "" (
          echo Can't see the ServiceHostingSDKInstallPath environment variable. Please run from a Windows Azure SDK command-line (run Program Files\Windows Azure SDK\^\bin\setenv.cmd^).
          GOTO :eof
      )
      rem Тут можно удалить временные файлы, остановить IIS и т.п.
      rem iisreset /stop
      rem Эта команда создает пакет для Windows Azure
      cspack Perl.csdef /out:Perl.cspkg
      popd

      Link to the archive with sample files: https://dl.dropboxusercontent.com/u/7840290/habrahabr/Perl.zip

      Run Perl.pack.cmd. The result is a Perl.cspkg file of 92mb in size. We will upload the files to Azure Cloud Services and make sure that the Mojolicious program works correctly by opening the link after the installation is complete.



      Java and ColdFusion (Railo)



      Lastly, there were Java and ColdFusion. As an alternative to ColdFusion, Helicon Zoo currently uses the free, open source Railo. I’ll make a reservation right away - I couldn’t install Java or Railo on Azure Cloud Services, and the reason for this is very trivial - the Azure package size limit. At least in my account you cannot upload packages larger than 200 mb in size. At the same time, Railo and most other server technologies in Java require Oracle JDK, the distribution size of which is 125 MB, which, together with other components, easily exceeds 200. However, I will nevertheless describe how Java programs should have started if not for that restriction. Perhaps the restriction will be removed in the future and the chapter will become relevant. Moreover, in general, launching Java programs is quite simple and convenient. Java developers do not need to learn to package components inside programs - for them this is standard behavior. Sites, programs and services in Java, as a rule, have a minimum of external dependencies and do not need complex environment settings.

      The main external dependency for Java programs is the Oracle JDK, and unfortunately it cannot be installed from the Helicon Zoo repository. Oracle prohibits embedding its JDK in other products and repositories and any delivery of their distributions bypassing the Oracle site itself. Therefore, you need to download JDK-7 yourself using this link: http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html For Azure Cloud Services, you will need the Windows-64 bit version. On your workstation, set the version according to the bit size of the machine. After JDK-7 is installed, you can install Java programs from the Helicon Zoo repository. For example, you can install Zoo -> Applications -> SCM Manager- A small manager and repository service for Git, Mercurial and SVN written in Java. Or put Zoo -> Applications -> Mura CMS - a beautiful CMS written in ColdFusion. Both programs are installed directly from the repository without additional steps.



      In my case, I installed Mura CMS in the folder “My Web Sites \ Mura CMS1”. Further, as before - we create an offline-package folder where we pack Java Hosting Package or CFML Hosting Package from the Helicon Zoo repository, depending on which technology is used:
      mkdir offline-package
      WebpiCmd.exe /offline /Products:CFMLHostingPackage /Path:"offline-package" /Feeds:http://www.helicontech.com/zoo/feed.xml


      Add to the offline-package \ bin directory the distribution downloaded from JDK-7 earlier. 
      The script bin \ startup.cmd will be distinguished by an additional call to the JDK-7 installer:

      [bin \ startup.cmd]
      echo Starting installation...
      rem Дать права на чтение и запись папке куда распаковано приложение
      icacls "%RoleRoot%\approot" /grant "Everyone":F /T
      rem Локальная папка AppData с правами на запись нужна для работы Web Platform Installer
      rem Создадим эту папку и ключ реестра на нее указывающий
      md "%RoleRoot%\appdata"
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d "%RoleRoot%\appdata" /f
      rem Перейдем в папку с WebpiCmd.exe
      pushd "%RoleRoot%\approot\offline-package\bin"
      rem Устанавливаем JDK-7
      jdk-7u45-windows-x64.exe /s
      rem Вызов команды WebpiCmd.exe для установки продукта из папки offline-package
      rem Обратите внимание на имя продукта – PerlHostingPackage, а также логи в install.txt и install-error.txt
      WebpiCmd.exe /install /Products:CFMLHostingPackage /XML:%RoleRoot%\approot\offline-package\feeds\latest\webproductlist.xml ^
                   /Feeds:%RoleRoot%\approot\offline-package\feeds\latest\supplementalfeeds\feed.xml ^
                   /AcceptEula  >%RoleRoot%\approot\install.txt 2>%RoleRoot%\approot\install-error.txt
      popd
      rem Вернуть старое значение ключу реестра с AppData
      reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" ^
          /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f
      rem Тут можно выполнить другие действия, например удалить временные файлы.
      echo Completed installation.

      Create the package files:

      [Mura.Cloud.cscfg]


      [Mura.csdef]


      [Mura.pack.cmd]
      @echo off
      set WINDOWS_AZURE_SDK_PATH="C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.1"
      call %WINDOWS_AZURE_SDK_PATH%\bin\setenv.cmd
      pushd %~dp0
      if "%ServiceHostingSDKInstallPath%" == "" (
          echo Can't see the ServiceHostingSDKInstallPath environment variable. Please run from a Windows Azure SDK command-line (run Program Files\Windows Azure SDK\^\bin\setenv.cmd^).
          GOTO :eof
      )
      rem Тут можно удалить временные файлы, остановить IIS и т.п.
      rem iisreset /stop
      rem Эта команда создает пакет для Windows Azure
      cspack Mura.csdef /out:Mura.cspkg
      popd

      And run Mura.pack.cmd. The result is a Mura.cspkg file of size 275 mb. What can I say: Java requires a lot of resources. Although 300 MB for transmission over a local area network by modern standards is not so much.

      Well, now, if Azure Cloud Services accepted packages of this size, we would just need to download these files to it. In the meantime, our experiment is purely theoretical.

      Conclusion



      Несмотря на кажущуюся сложность показанного решения, не все так страшно. За одну статью мы управились сразу с большинством популярных технологий веб разработки. Разумеется, остались еще PHP и ASP.NET, которые и так неплохо описаны в инструкциях к Windows Azure. В репозитории Helicon Zoo есть еще PHP Hosting Package, которым удобно воспользоваться вместо стандартного решения от Microsoft в том случае если вы собираетесь смешивать несколько версий PHP или другие веб технологии в рамках одного сайта, так как в Zoo неплохо реализована изоляция технологий.

      The main advantage of the presented solution, in addition to relative simplicity and good performance, is the relatively easy migration of applications between servers and services. Using this solution, you leave for yourself a theoretical opportunity in the future to "jump" from Azure services if the conditions do not satisfy you. All applications described in this article can be similarly launched on almost any Windows and Linux server. Of course, the Azure infrastructure provides a host of other useful services, such as Media Services, Mobile Services, SQL Databases, or message queues. If your application will actively use these services, then binding to the platform will be more stringent.

    Also popular now: