Part 2: Creating a Composer enabled PHP website on Windows Azure with Git deployment


Introduction

This is part 2 of a 2 part blog post. Read part 1 here.

So in part 1, we’ve created a local Symfony2 PHP website that uses Composer to manage its packages. In this part, we are going to create a Windows Azure Website, setup deployment from source control, and modify the Git post deployment script to automatically run run php composer.phar install after each commit.

Why would you want to do that you ask? Well, the vendors directory, where all the downloaded packages reside, can get quite large, and storing it in source control, and uploading it with your website is a waste of bandwidth.

Creating the website

I’m not going to go through the details here, as it is a well covered topic, I’ll create the website on the portal, and choose to “Publish from source control”

image

And then choose “Local Git repository”

image

Fire it up! Bam, 5 seconds, I have a website created.

Create the local Git repo

Go to the Deployments tab for the website, then follow the steps there to create a local repository on my machine and commit my files. I’ll run the commands on Git Bash. Only commit the files locally, don’t add the remote Windows Azure repository and push just yet!

image

What we need to do now is to modify what happens whenever I commit files. Fortunatley, the great guys at the Windows Azure team have a tool called Kudu which is basically responsible for deploying your code once you push it to a Git source control.

Create the custom Kudo deployment script

For this part, you will need to have the Windows Azure Command Line Tools (CLI) installed.

Once you have it installed, you can launch the Windows Azure Command Prompt that got installed (which you will find under C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.2 or whichever version the SDK is current at the time you read this)

If you type azure in that prompt, you will get all the commands that you can use. The command we are interested in is azure site

image

So change directory into our project location then run the following

azure site deploymentscript --php -t bash 

Which will generate a .deployment file and a deploy.sh file. This deploy.sh file is what is executed after each push we do on the Windows Azure Git repo.

Customize the deploy.sh script to run composer

Open deploy.sh in your favorite editor

Add the below before the Deployment section

##################################################################################################################################
# Download Composer
# ----------
echo Downloading Composer
curl -sS https://getcomposer.org/installer | php

Add the below after the Deployment section

##################################################################################################################################
# Dependency install
# ----------
 
# Invoke Composer in the deployment directory
echo Invoking composer install in deployment directory $DEPLOYMENT_TARGET
php -d extension=php_intl.dll $DEPLOYMENT_TARGET/composer.phar install -v --prefer-dist --no-dev --optimize-autoloader --no-interaction

 

Commit the newly added files to your local repository

git add –-all
git commit -m "added deployment scripts"

Add the remote Windows Azure repository and push to it

git remote add azure https://sabbour@symfonycomposer.scm.azurewebsites.net:443/symfonycomposer.git
git push azure master

You’re done

You’ll see that I’ve only pushed 270KB and on the server, the composer script kicked in and started downloading all the dependencies without using my bandwidth. Talk about efficiency!

Counting objects: 168, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (153/153), done.
Writing objects: 100% (168/168), 269.25 KiB | 0 bytes/s, done.
Total 168 (delta 48), reused 0 (delta 0)
 
remote: Updating branch 'master'.
remote: Updating submodules.
remote: Preparing deployment for commit id '623af14f72'.
remote: Running custom deployment command...
remote: Running deployment command...
remote: Using php.ini from: C:/DWASFiles/Sites/symfonycomposer/Config/PHP-5.4.9/php.ini
remote: Downloading Composer
remote: #!/usr/bin/env php
remote: All settings correct for using Composer
remote: Downloading...
remote:
remote: Composer successfully installed to: D:\home\site\repository\composer.phar
remote: Use it: php composer.phar
remote: Handling Basic Web Site deployment.
remote: KuduSync.NET from: 'D:\home\site\repository' to: 'D:\home\site\wwwroot'
remote: Copying file: '.gitignore'
 
----- [ REMOVED FOR BREVITY ] -----
 
remote: Copying file: 'src\Acme\DemoBundle\Resources\public\images\welcome-demo.gif'
remote: Omitting next output lines...
remote: Invoking composer install in D:\home\site\wwwroot
remote: Loading composer repositories with package information
remote: Installing dependencies from lock file
remote: Warning: The lock file is not up to date with the latest changes in comp
oser.json. You may be getting outdated dependencies. Run update to update them.
remote:   - Installing doctrine/lexer (v1.0)
remote:     Downloading: 100%
remote:     Extracting archive
 
----- [ REMOVED FOR BREVITY ] -----
 
remote:   - Installing twig/extensions (v1.0.1)
remote:     Downloading: 100%
remote:     Extracting archive
 
----- [ REMOVED FOR BREVITY ] -----
 
remote: Generating optimized autoload files
remote: ........................................................................
..........................................
remote: Creating the "app/config/parameters.yml" file
remote: ..........
remote: Clearing the cache for the dev environment with debug true
remote: ..........
remote: Installing assets using the hard copy option
remote: Installing assets for Symfony\Bundle\FrameworkBundle into web/bundles/fr
amework
remote: Installing assets for Acme\DemoBundle into web/bundles/acmedemo
remote: Installing assets for Sensio\Bundle\DistributionBundle into web/bundles/
sensiodistribution
 
remote: Finished successfully.
remote: Deployment successful.
To https://sabbour@symfonycomposer.scm.azurewebsites.net:443/symfonycomposer.git
 
 * [new branch]      master -> master

Next steps

You need to take care of some things when migrating from an Apache based installation to an IIS based installation (like Windows Azure Websites). For example, IIS uses Web.config (in contrast to Apache's .htaccess) to configure stuff, like URL Rewriting.

You may use these excellent posts to understand how to translate .htaccess content to Web.config and if you are running Windows, you can even use a tool provided inside IIS Manager to do the conversion for you.

Note: This post is cross posted to my new blog at http://sabbour.me/

Comments (3)

  1. Ernest John says:

    This is very awesome since PHP developers now break the myth of Azure only being for ASP.NET. Now they know Composer is well integrated and usable on Azure

  2. Adam Anderly says:

    Is this still working for you? I got your example setup for a Laravel-based app and it triggers, but keeps hanging on "Generating autoload files". Checking the deployment log I get the following error. Have you run into this?

    Generating autoload files

     [SymfonyComponentProcessExceptionRuntimeException]  

     Unable to kill the process                              

    install [–prefer-source] [–prefer-dist] [–dry-run] [–dev] [–no-dev] [–no-plugins] [–no-custom-installers] [–no-autoloader] [–no-scripts] [–no-progress] [-v|vv|vvv|–verbose] [-o|–optimize-autoloader] [–ignore-platform-reqs] [packages1] … [packagesN]

    Fatal error: Uncaught exception 'SymfonyComponentProcessExceptionRuntimeException' with message 'Unable to kill the process' in phar://D:/home/site/wwwroot/bin/composer.phar/vendor/symfony/process/Symfony/Component/Process/Process.php:793

    Stack trace:

    #0 phar://D:/home/site/wwwroot/bin/composer.phar/vendor/symfony/process/Symfony/Component/Process/Process.php(177): SymfonyComponentProcessProcess->stop()

    #1 [internal function]: SymfonyComponentProcessProcess->__destruct()

    #2 {main}

     thrown in phar://D:/home/site/wwwroot/bin/composer.phar/vendor/symfony/process/Symfony/Component/Process/Process.php on line 793

    PHP Fatal error:  Uncaught exception 'SymfonyComponentProcessExceptionRuntimeException' with message 'Unable to kill the process' in phar://D:/home/site/wwwroot/bin/composer.phar/vendor/symfony/process/Symfony/Component/Process/Process.php:793

    Stack trace:

    #0 phar://D:/home/site/wwwroot/bin/composer.phar/vendor/symfony/process/Symfony/Component/Process/Process.php(177): SymfonyComponentProcessProcess->stop()

    #1 [internal function]: SymfonyComponentProcessProcess->__destruct()

    #2 {main}

     thrown in phar://D:/home/site/wwwroot/bin/composer.phar/vendor/symfony/process/Symfony/Component/Process/Process.php on line 793

Skip to main content