Desplegar web app con Symfony en Azure App Service Windows

Estos días he estado jugando con algunas aplicaciones en PHP y he estado buscando la manera más rápida de desplegar en Azure App Service con Windows una aplicación que utiliza el famoso framework Symfony. Para mostrártelo, voy a crear una aplicación muy sencilla, que me permita comprobar que todo funciona correctamente. Lo primero que vamos a hacer es utilizar el siguiente comando para generar el esqueleto de una aplicación con este framework (si es la primera vez que trabajas con Symfony, te recomiendo que sigas este tutorial de la documentación oficial):

composer create-project symfony/website-skeleton symfony-on-azure

Creación del proyecto Symfony

Una vez que se ha creado el proyecto, vamos a ejecutarlo con el siguiente comando, dentro de la carpeta del proyecto, para comprobar que en local funciona correctamente:

php bin/console server:run

Ejecutando el proyecto de Symfony en local

Abre el navegador y accede a http://localhost:8000/

Proyecto de symfony ejecutandose en local

¡Genial! Si has obtenido esta página significa que tu proyecto está listo para comenzar a trabajar. No vamos a modificar mucho de él pero si que vamos a crear un controlador con una ruta asociada con el fin de poder comprobar en Azure que estas funcionan correctamente:

<?php
// src/Controller/HelloAzureController.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class HelloAzureController
{
    /**
     * @Route("/hello/azure")
     */
    public function hello()
    {
        return new Response(
            '<html><body><h1>Hello Symfony from Microsoft Azure</h1></body></html>'
        );
    }
}

Instala annotations para que puedas utilizar la definición de rutas a través de anotaciones:

composer require annotations

Comprueba que la ruta funciona correctamente a través de la siguiente URL: http://localhost:8000/hello/azure

Hello Symfony from Microsoft Azure

Como último paso, antes de hacer el despliegue, crea dentro de tu proyecto el archivo web.config con el siguiente contenido:

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <clear />
        <rule name="BlockAccessToPublic" patternSyntax="Wildcard" stopProcessing="true">
          <match url="*" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
            <add input="{URL}" pattern="/public/*" />
          </conditions>
          <action type="CustomResponse" statusCode="403" statusReason="Forbidden: Access is denied." statusDescription="You do not have permission to view this directory or page using the credentials that you supplied." />
        </rule>
        <rule name="RewriteAssetsToPublic" stopProcessing="true">
          <match url="^(.*)(\.css|\.js|\.jpg|\.png|\.gif|\.ico)$" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
          </conditions>
          <action type="Rewrite" url="public/{R:0}" />
        </rule>
        <rule name="RewriteRequestsToPublic" stopProcessing="true">
          <match url="^(.*)$" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
          </conditions>
          <action type="Rewrite" url="public/index.php/{R:0}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Esto me permite reescribir el paths para que todas las peticiones pasen por public/index.php y que Symfony sepa a qué controlador debe mandar la petición.

El código del ejemplo lo he alojado en GitHub con el objetivo de poder versionarlo, además de ayudarme con la integración continua, que configuraremos después. Los comando que he utilizado para hacer la subida a Github han sido los siguientes:

git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/0GiS0/symfony-on-azure.git
git push -u origin master

El proyecto de Symfony genera de manera automática el archivo .gitignore por lo que no será necesario que te preocupes de esta parte.

Ahora ha llegado el momento de crear un nuevo App Service con la configuración para Windows:

App Service – symfony-on-azure

En el apartado Application settings modifica la versión de PHP, que por defecto es a día de hoy la 5.6, a la versión 7.2. Haz clic en el botón Save para guardar los cambios.

App Service – Application Settings – PHP 7.2

Una vez creado, el siguiente paso es habilitar la integración continua a través de la sección Deployment Center de tu App Service. En esta sección tenemos un asistente que nos facilitará mucho el trabajo a la hora de configurar la integración. Como vamos a asociar este proceso a Azure DevOps, te recomiendo que crees el proyecto donde se van a alojar las pipelines antes de iniciar el asistente. Accede a Azure DevOps a través de https://TU_CUENTA.visualstudio.com/ y crea un proyecto nuevo, a través del botón Create project.

Azure DevOps – Create new project

Una vez creado inicia el asistente y sigue estos pasos:

  1. Source Control: Elige GitHub y haz clic en el botón Continue.

    App Service – Deployment Center – Source Control – GitHub

  2. Build provider: Para este ejemplo vamos a utilizar la opción VSTS Build (Preview) la cual nos permite utilizar Azure DevOps (anteriormente Visual Studio Team Services) y que nos creará las pipelines de Build y de Releases de manera automática para construir nuestro paquete de subida a App Service.

    App Service – Deployment Center – Build Provider – VSTS Build Preview

    Las pipelines solo son las recetas o listas de tareas que necesita el proceso de Build o de Release para llegar al objetivo, que será generar el paquete y realizar el despliegue.

  3. Configure: este apartado es el pegamento entre tu código fuente en GitHub y tu proyecto en Azure DevOps. Selecciona el repositorio que quieres utilizar y cuál es el proyecto donde quieres generar las pipelines de Build y de Release. Selecciona además como Web Application Framework la opción PHP.

    App Service – Deployment Center – Configure

  4. Test: Este apartado déjalo como está, por defecto a No.

    App Service – Deployment Center – Test – No

  5. Summary: este apartado es solo un resumen de todo lo que acabas de configurar. Haz clic en Finish para que comience el proceso de generación de las pipelines. Este tardará unos minutos.

    App Service – Deployment Center – Summary

Una vez completado el asistente con Development Center se hará una primera descarga desde GitHub de la última versión de tu código fuente y pasará por las fases de Build y Release en Azure DevOps. Una vez completado el flujo aparecerá reflejado en esta misma pestaña, donde desaparecerá el asistente y se mostrará el histórico.

Para comprobar que todo ha sido configurado correctamente, accede a tu aplicación a través de la URL elegida durante la creación del App Service.

Probando la página de bienvenida de Symfony en Azure

Prueba también la ruta que hemos configurado y ver qué todo funciona como se espera:

Probando las rutas de Symfony en Azure

¡Saludos!