miércoles, 8 de abril de 2015

¿Como poner en producción un proyecto Symfony 2?

Symfony 2 es uno de los frameworks MVC basados en lenguaje PHP que más de moda están en los últimos tiempos. La documentación oficial de Symfony 2 es muy extensa, pero se hecha en falta una sección dedicada sobre como poner en producción un proyecto ya terminado (o una beta) en un servidor real. Lo que llamamos desplegar el proyecto (del inglés deploy).

Los requisitos de Symfony 2 no son demasiado elevados: Basta un servidor web como Apache o Nginx y PHP 5.3.3 o superior (aunque se recomienda PHP superior a 5.3.16). Siempre es recomendable aunque no obligatorio que sea un servidor dedicado sobre el que tengamos acceso root. Es perfectamente posible desplegar un proyecto Symfony 2 en un servidor compartido aunque eso sí: es necesario tener acceso al shell del servidor (vía SSH típicamente). Symfony 2 no puede desplegarse simplemente subiendo los archivos por FTP.


Conceptos previos

Cualquier proyecto Symfony 2 está compuesto por una carpeta de código fuente del proyecto (src), una carpeta de librerías externas entre las que se incluye el propio framework (vendors), una carpeta de configuración y recursos globales (app) y una carpeta frontal (web). Todas ellas son necesarias, pero no todas tienen la misma importancia.

Carpetas de un proyecto Symfony

  • app: Esta carpeta contiene la configuración del proyecto (subcarpeta app/config), pero también los recursos comunes (subcarpeta app/Resources), los logs (subcarpeta app/logs) y también la cache (subcarpeta app/cache), que es donde se crean una serie de clases autogeneradas que aceleran la ejecución del proyecto (es algo similar a tener código compilado sólo que sigue siendo PHP). En la carpeta app también está la consola que es un componente necesario para instalar el proyecto.
  • src: Esta carpeta contiene el código fuente del proyecto. Internamente el código se divide en bundles y cada bundle puede tener controladores, entidades, vistas, recursos, etc.
  • vendor: Esta carpeta contiene el código fuente de las librerías externas y bundles que usa el proyecto. Se trata de código es open-source que sus creadores ponen a disposición de los programadores para desarrollar sus propios proyectos.
  • web: Esta carpeta contiene el controlador frontal de Symfony 2 (programa app.php). Un proyecto Symfony 2 puede tener más de un controlador frontal, según los distintos entornos de ejecución que se definan: app_dev.php, app_test.php, etc. A la hora de ponerlo en explotación bastaría con el controlador frontal del entorno de producción producción. En la carpeta web también se copian automáticamente los assets del proyecto (imágenes, CSS, JS, etc.)

Entornos de un proyecto Symfony

Dentro de un único proyecto Symfony 2 se pueden definir diversos entornos; típicamente son tres, aunque pueden ser más: desarrollo (dev), pruebas (test) y producción (prod). El primero se usa para desarrollar en proyecto, el segundo es para pasar los test unitarios y funcionales y el tercero es para probar el proyecto tal y como debe funcionar en explotación.

Ojo: Nunca han que confundir los entornos de Symfony (dev, test, prod) con los entornos de una organización. Son cosas distintos. A la hora de poner en producción un proyecto Symfony 2 en un servidor real sólo tendremos en cuenta el entorno de producción. Los demás deben descartarse.

Cada entorno Symfony 2 tiene archivos de configuración diferentes en la carpeta app/config:

  • config.yml: Archivo de configuración común para todos los entornos.
  • config_dev.yml: Archivo de configuración del entorno de desarrollo de Symfony 2. Modifica la configuración de config.yml para el entorno dev. Permite por ejemplo evitar que se envíen mails al ejecutar los test.
  • config_test.yml: Archivo de configuración del entorno Symfony 2 de pruebas unitarias.
  • config_prod.yml: Archivo de configuración específico del entorno de producción.

Además del archivo de configuración puede haber otros archivos con configuración adicional:

  • security.yml: Configuración de la seguridad del proyecto Symfony 2.
  • routing.yml: Configuración de las rutas del proyecto Symfony 2.
  • routing_dev.yml, routing_test.yml, … rutas adicionales por entornos.

Por último existen dos archivos de configuración adicionales:

  • parameters.yml: Este archivo contiene la configuración dependiente de la instalación y es el único archivo que debería variar de un servidor a otro. Sirve por ejemplo para indicar la base de datos a usar, el servidor del API, el servidor de correo, etc. NUNCA debería distribuirse este archivo en una puesta en explotación.
  • parameters.yml.dist: Indica los valores por defecto del archivo “parameters.yml” y es usado por “composer.phar” para crear este último.

Por cada entorno Symfony 2 también habrá un controlador frontal en la carpeta web. Es decir que además del controlador app.php podremos tener app_dev.php y app_test.php. Si por ejemplo creamos un archivo config_beta.yml automáticamente se creará un controlador app_beta.php.

Herramientas

  • composer.phar: Herramienta para resolver dependencias en un proyecto PHP. Usado por Symfony 2 para instalar los vendor y para preparar los entornos.
  • app/console.php: Herramienta interna de Symfony 2 que permite limpiar la cache, instalar los assets y muchas más cosas.

Punto de partida

Para poner en producción un proyecto Symfony 2 hay dos puntos de partida:

  1. Partir de un repositorio (GIT, SVN, etc.)
  2. Partir de código fuente con los vendor.

Permisos

Debido a que es necesario que las carpetas app/cache y app/logs tengan permiso de escritura se recomienda que el usuario Linux que realice la instalación sea el mismo del servidor web (apache, nginx, etc). Si esto no fuera posible debería modificarse el propietario de todos los archivos de esas carpetas como paso final de la instalación o bien dar permisos de escritura sobre esas carpetas. Si esto no se hace no funcionará el proyecto.


Partiendo de un repositorio (GIT, SVN, etc.)

Pasos a seguir

  1. Copiar el proyecto desde el repositorio.
  2. Instalar los vendor.
    php composer.phar install
  3. Borrar controladores frontales y archivos de configuración sobrantes.
    rm -f app/config/*_dev.yml
    rm -f app/config/*_test.yml
    rm -f web/app_dev.yml
    rm -f web/app_test.yml
    (...)
  4. Copiar el archivo app/config/parameters.yml específico de esta instalación.
  5. Limpiar e inicializar la cache de Symfony 2.
    php app/console -e=prod cache:clear
  6. Instalar los assets del entorno de producción.
    php app/console assets:install web --symlink
    php app/console -e=prod assetic:dump
  7. Opcionalmente cambiar el propietario de las carpetas cache y logs.
    chown -R nginx:nginx app/cache
    chown -R nginx:nginx app/logs
  8. Opcionalmente dar permisos de escritura a las carpetas cache y logs.
    chmod -R a+w app/cache
    chmod -R a+w app/logs

Partiendo del código fuente completo (incluido vendor).

Lo normal es que un proyecto Symfony 2 se despliegue desde un repositorio de fuentes (GIT, SVN, etc), pero en ocasiones esto no es posible. En ese caso habrá que subir manualmente el código fuente al servidor, incluyendo la carpeta vendor.

Pasos a seguir

  1. Copiar todo el proyecto Symfony 2 a la carpeta de destino.
  2. Borrar las carpetas de “cache” y “logs”.
    rm -rf app/cache/*
    rm -rf app/logs/*
  3. Borrar controladores frontales y archivos de configuración sobrantes.
    rm -f app/config/*_dev.yml
    rm -f app/config/*_test.yml
    rm -f web/app_dev.yml
    rm -f web/app_test.yml
    (...)
  4. Copiar el archivo app/config/parameters.yml específico de esta instalación.
  5. Limpiar e inicializar la cache de Symfony 2.
    php app/console -e=prod cache:clear
  6. Instalar los assets del entorno de producción.
    php app/console assets:install web --symlink
    php app/console -e=prod assetic:dump
  7. Opcionalmente cambiar el propietario de las carpetas cache y logs.
    chown -R nginx:nginx app/cache
    chown -R nginx:nginx app/logs
  8. Opcionalmente dar permisos de escritura a las carpetas cache y logs.
    chmod -R a+w app/cache
    chmod -R a+w app/logs