Azure et PHP : comment installer le runtime

by pierre couzy 30. March 2011 16:57

Depuis novembre 2010, les évolutions de Windows Azure ont ouvert les fonctionnalités de Windows Azure, mais ces évolutions ont également apporté quelques différences de fonctionnement, notamment pour l'installation de PHP sur Azure. Voici donc les méthodes que j'ai pu trouver, et une opinion sur leur intérêt.

Installation de PHP dans Hosted Web Core

Cette technique est celle qui était préconisée avant la disponibilité de Full IIS dans Azure, et elle repose sur l'installation de PHP depuis un Web Role. Cette technique est toujours utilisable, mais il faut retoucher légèrement les projets fournis en standard par Visual Studio. En effet, le mode de paramétrage change entre IIS et Hosted Web Core. Dans Hosted Web Core, les paramètres de votre site Web sont logiquement dans Web.Config, mais vous pouvez également prendre la main sur le paramétrage d'IIS en vous appuyant sur le fichier web.roleconfig. Voici par exemple la déclaration de PHP au module fastCGI et son utilisation sur le site web :

web.roleconfig :

<configuration>
  <system.webServer>
    <fastCgi>
      <application fullPath="e:\approot\php\php-cgi.exe"/>
    </fastCgi>
  </system.webServer>
</configuration> 

 

Web.config :

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
      <add name="PHPFastcgi" verb="*" 
           path="*.php" scriptProcessor="e:\approot\php\php-cgi.exe" 
           modules="FastCgiModule" resourceType="Either" />
    </handlers>
     ...

Malheureusement, cette belle mécanique ne fonctionne pas dans le mode Full IIS (le fichier web.roleconfig est ignoré), et la solution pour la rétablir consiste simplement à forcer votre Web Role à revenir en mode Hosted Web Core, en modifiant le fichier csdef qui définit vos rôles, et en supprimant la sections sites :

 

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="JoomlaDansAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="JoomlaWeb" vmsize="ExtraSmall">
<!--
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
-->    
    <Endpoints>
      
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
      <Import moduleName="RemoteAccess" />
      <Import moduleName="RemoteForwarder" />
    </Imports>
  </WebRole>
  
</ServiceDefinition>

 

Un grand merci au passage au blog d'Avkash Chauhan qui contient un paquet de choses intéressantes sur les évolutions d'Azure.

Installation de PHP par le biais de WebPI

C'est la technique actuellement présentée dans la majorité des posts, et elle repose sur un principe assez simple : au lieu de procéder soi-même à l'installation de PHP, on délègue cette tâche à quelque chose qui le fait déjà, et qui est en plus capable de gérer les dépendances.

Cette délégation d'installation se fait dans une startup task : juste avant d'insérer votre nouvelle instance dans le load balancer, on exécute un certain nombre de tâches sous la forme suivante :

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="InstallPHP" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="PHPWebRole">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="HttpIn" endpointName="HttpIn" />
        </Bindings>
      </Site>
    </Sites>
    <ConfigurationSettings>
    </ConfigurationSettings>
    <Startup>
      <Task commandLine="InstallPHP.cmd" executionContext="elevated" taskType="simple" />
    </Startup>
    <Endpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
      <Import moduleName="RemoteAccess" />
      <Import moduleName="RemoteForwarder" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Le fichier InstallPHP.cmd fait ensuite appel à webPI pour sélectionner la version de PHP à installer (regarder dans le Windows Azure Training Kit pour en savoir plus). Le souci, c'est que si vous voulez avoir plus de contrôle sur l'installation, il faut soit créer ses propres feeds (compliqué et fragile), soit enchaîner les installations avec WebPI en priant pour ne pas avoir de dépendance incompatible avec Azure (et il y a un hotfix de Windows 2008 qui ne s'applique pas à Azure, entre autre choses qui peuvent bloquer l'installation).

De plus, impossible de définir avec précision son php.ini ou d'ajouter une extension.

Installation manuelle de PHP dans Azure en mode Full IIS

C'est la technique que je suis en train d'explorer et pour le moment j'en suis content (mais je n'ai pas encore couvert tous les cas possibles). L'idée est de revenir au modèle proposé par Hosted Web Core. Le problème de Full IIS est qu'il est impossible de paramétrer correctement les composants d'IIS qui ne sont pas sous le contrôle de Web.Config. Après avoir un peu tourné autour du problème et lu la documentation d'installation manuelle de PHP sous IIS faite par Ruslan Yakushev, j'ai utilisé le Web.Config et une startup task.

Le début du packaging est strictement identique à celui de PHP en mode HWC : on pose son runtime dans un répertoire PHP à la racine du site Web (on peut également le déporter ailleurs sur le disque si on le souhaite en utilisant d'autres startup tasks, mais je n'ai pas encore peaufiné assez pour m'occuper de ce genre de configuration).

On insère ensuite une startup task de la forme suivante dans le csdef :

    <Startup>
      <Task commandLine="PHP\InstallPHP.cmd" executionContext="elevated" taskType="simple"></Task>
    </Startup>

Et le fichier InstallPHP.cmd fait simplement ce que faisait web.roleconfig en mode Hosted Web Core :

rem Creating IIS FastCGI process pool
%windir%\system32\inetsrv\appcmd set config /section:system.webServer/fastCGI /+[fullPath='e:\approot\php\php-cgi.exe'] > PHPInstallLog.txt

rem Creating handler mapping for PHP requests
%windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /+[name='PHP_via_FastCGI',path='*.php',verb='*',modules='FastCgiModule',scriptProcessor='e:\approot\php\php-cgi.exe',resourceType='Either'] >> PHPInstallLog.txt

rem Configuring FastCGI and PHP recycling
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /[fullPath='E:\AppRoot\PHP\php-cgi.exe'].instanceMaxRequests:10000 >> PHPInstallLog.txt
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='E:\AppRoot\PHP\php-cgi.exe'].environmentVariables.[name='PHP_FCGI_MAX_REQUESTS',value='10000']" >> PHPInstallLog.txt

rem Configuring FastCGI timeout settings
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /[fullPath='E:\AppRoot\PHP\php-cgi.exe',arguments=''].activityTimeout:"90"  /commit:apphost >> PHPInstallLog.txt
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /[fullPath='E:\AppRoot\PHP\php-cgi.exe',arguments=''].requestTimeout:"90"  /commit:apphost >> PHPInstallLog.txt

rem Changing the location of php.ini file
appcmd.exe set config  -section:system.webServer/fastCgi /+"[fullPath='e:\approt\php\php.exe',arguments=''].environmentVariables.[name='PHPRC',value='e:\approt\php\']" /commit:apphost >> PHPInstallLog.txt

A noter : en mode Full IIS, le package est déployé deux fois, une à la racine de approot et une dans un sous-répertoire qui est physiquement utilisé par IIS. La technique de déploiement ci-dessus utilise la version déployée dans AppRoot, ce qui permet de supprimer le répertoire PHP du répertoire utilisé par IIS afin de ne pas déployer le runtime PHP dans une zone du filesystem accessible en http.

Attention à un dernier détail : si vous préférez faire l'association entre votre site et FastCGI en utilisant web.config, l'exemple fourni dans les web roles CGI est incorrect : en effet, il utilise %RoleRoot% pour désigner le lecteur où est installé votre package dans la VM Azure, mais cette variable d'environnement n'est pas disponible au moment où le Web.Config est parsé, et il faut donc coder en dur E: de cette façon :

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <handlers>

      <add name="PHPHandler"
           verb="*"
           path="*.php"
           scriptProcessor="E:\approot\php\php-cgi.exe"
           modules="FastCgiModule"
           resourceType="Either" />

    </handlers>
  </system.webServer>
</configuration>

Tags:

Azure | php

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading