Symfony 1.4, la guía definitiva

16.5. Instalando aplicaciones

Symfony dispone de comandos para sincronizar 2 versiones diferentes de un mismo sitio web. La utilidad de estos comandos es la de poder instalar una aplicación o sitio web desde un servidor de desarrollo hasta un servidor de producción, desde donde los usuarios accederán a la aplicación pública. Este proceso también se conoce como el "deploy" de una aplicación, por lo que a veces se utiliza la palabra "deployar" (o "desplegar") para referirse a la instalación de una aplicación.

16.5.1. Preparando un proyecto para transferirlo con FTP

La forma habitual de instalar las aplicaciones en los servidores de producción consiste en trasferir todos los archivos de la aplicación mediante FTP (o SFTP). Sin embargo, los proyectos desarrollados con Symfony utilizan las librerías internas de Symfony y, salvo que se desarrolle con el archivo de pruebas sandbox (lo que no se recomienda) o salvo que los directorios lib/ y data/ estén enlazados mediante svn:externals, estas librerías no se encuentran dentro de los directorios del proyecto. Independientemente de que se realice una instalación PEAR o se utilicen enlaces simbólicos, trasladar la misma estructura de directorios al servidor de producción suele ser una tarea costosa y no muy sencilla.

Por este motivo, Symfony dispone de una utilidad que congela los proyectos, es decir, copia todas las librerías de Symfony necesarias en los directorios data/, lib/ y web/ del proyecto. Una vez congelado, el proyecto se transforma en una aplicación independiente y completamente ejecutable por sí misma, tal y como el entorno de pruebas sandbox.

> php symfony project:freeze symfony_data_dir

El argumento symfony_data_dir es la ruta al directorio data de Symfony. Si has instalado Symfony mediante Subversion o mediante un archivo con el código fuente, este directorio coincide con el directorio lib de Symfony. Si has instalado Symfony mediante un paquete PEAR, este directorio se encuentra bajo el directorio de datos de PEAR.

Una vez que un proyecto ha sido congelado, se puede transferir directamente el directorio raíz completo del proyecto al servidor de producción y funciona sin necesidad de PEAR, enlaces simbólicos o cualquier otro elemento.

Nota En un mismo servidor se pueden ejecutar simultáneamente varios proyectos congelados, cada uno con su propia, e incluso diferente, versión de Symfony.

Para devolver un proyecto a su estado original, se utiliza la tarea project:unfreeze descongelar). Esta tarea borra los directorios data/symfony/, lib/symfony/ y web/sf/.

> php symfony project:unfreeze

Si antes de congelar el proyecto existían enlaces simbólicos, Symfony es capaz de reconocerlos y al descongelar el proyecto, vuelve a crear los enlaces simbólicos originales.

16.5.2. Usando rsync para transferir archivos incrementalmente

Cuando se realiza el primer traspaso de la aplicación web, es útil transferir mediante FTP (o SFTP) el directorio raíz completo del proyecto, pero cuando se trata de actualizar una aplicación para la que solamente se han modificado unos pocos archivos, la solución mediante FTP no es la ideal. Si se utiliza FTP, o se vuelve a transferir completo el proyecto, con el consiguiente gasto de tiempo y ancho de banda, o se accede manualmente a todos los directorios con archivos modificados y se suben de uno en uno. Este último método, no solo es costoso en tiempo, sino que es muy propenso a cometer errores. Además, el sitio web puede estar no disponible o puede mostrar muchos errores durante el traspaso de las modificaciones.

La solución que propone Symfony es el uso de la herramienta de syncronización rsyn mediante SSH. Rsync (http://samba.anu.edu.au/rsync/) es una utilidad de la línea de comandos que permite realizar una transferencia incremental de archivos de forma muy rápida, además de que es una herramienta de software libre. En una transferencia incremental, solamente se transfieren los datos modificados. Si un archivo no ha sido modificado desde la última sincronización, no se vuelve a enviar al servidor. Si un archivo solamente tiene un cambio parcial, solamente se envían los cambios realizados. La principal ventaja de rsync es que las sincronizaciones requieren el envío de muy pocos datos y por tanto, son muy rápidas.

Symfony utiliza SSH conjuntamente con rsync para hacer más segura la transferencia de datos. La mayoría de servicios de hosting soportan el uso de SSH para aportar más seguridad a la transferencia de archivos hasta sus servidores.

El cliente SSH utilizado por Symfony utiliza las opciones de conexión del archivo config/properties.ini. El listado 16-19 muestra un ejemplo de las opciones de conexión para un servidor de producción. Antes de realizar la sincronización de la aplicación, se deben establecer las opciones de conexión en este archivo. También es posible definir una opción llamada parameters para utilizar parámetros propios con rsync.

Listado 16-19 - Opciones de conexión para la sincronización con un servidor, en miproyecto/config/properties.ini

[symfony]
  name=miproyecto

[production]
  host=frontend.example.com
  port=22
  user=myuser
  dir=/home/myaccount/miproyecto/

Nota No debe confundirse el servidor de producción (que es el servidor definido en el archivo properties.ini del proyecto) con el entorno de producción (el controlador frontal y la configuración que se utiliza en producción).

Como la sincronización de rsync mediante SSH requiere de varios comandos, y la sincronización suele ocurrir muchas veces durante la vida de una aplicación, Symfony automatiza esta tarea mediante un único comando:

> php symfony project:deploy production

El comando anterior ejecuta el comando rsync en el modo de prueba; es decir, muestra los archivos que tienen que ser sincronizados, pero no los sincroniza realmente. Para realizar la sincronización, se debe indicar explícitamente mediante la opción --go.

> php symfony project:deploy production --go

No debe olvidarse borrar la cache en el servidor de producción después de la sincronización.

Nota En ocasiones, se producen errores en el servidor de producción que no existían en el servidor de desarrollo. El 90% de las veces el problema reside en una diferencia en las versiones de las aplicaciones (de PHP, del servidor web o de la base de datos) o en la configuración de la aplicación. Para evitar sorpresas desagradables, se debe definir la configuración de PHP del servidor de producción en un archivo llamado php.yml, para poder comprobar que el entorno de desarrollo aplica las mismas ocpiones. El Capítulo 19 incluye más información sobre este archivo de configuración.

16.5.3. Ignorando los archivos innecesarios

Cuando se sincroniza un proyecto Symfony con un servidor de producción, algunos archivos y directorios no deberían transferirse:

  • Todos los directorios del versionado del código (.svn/, CVS/, etc.) y su contenido, solamente es necesario para el desarrollo e integración de la aplicación.
  • El controlador frontal del entorno de desarrollo no debería ser accesible por los usuarios finales. Las herramientas de depuración y de log disponibles en este controlador frontal penalizan el rendimiento de la aplicación y proporcionan mucha información sobre las variables internas utilizadas por las acciones. Siempre debería eliminarse este controlador frontal en la aplicación pública.
  • Los directorios cache/ y log/ del proyecto no deben borrarse cada vez que se realiza una sincronización. Estos directorios también deberían ignorarse. Si se dispone de un directorio llamado stats/, también debería ignorarse.
  • Los archivos subidos por los usuarios tampoco deberían transferirse. Una de las buenas prácticas recomendadas por Symfony es la de guardar los archivos subidos por los usuarios en el directorio web/uploads/. De esta forma, se pueden excluir todos estos archivos simplemente ignorando un directorio durante el traspaso de la aplicación.

Para excluir los archivos en las sincronizaciones de rsync, se edita el archivo rsync_exclude.txt que se encuentra en el directorio miproyecto/config/. Cada fila de ese archivo debe contener el nombre de un archivo, el nombre de un directorio o un patrón con comodines *. La estructura de archivos de Symfony está organizada de forma lógica y diseñada de forma que se minimice el número de archivos o directorios que se deben excluir manualmente de la sincronización. El listado 16-20 muestra un ejemplo.

Listado 16-20 - Ejemplo de exclusiones en una sincronización rsync, en miproyecto/config/rsync_exclude.txt

.svn
/cache/*
/log/*
/stats/*
/web/uploads/*
/web/frontend_dev.php

Nota Los directorios cache/ y log/ no deben sincronizarse con el servidor de producción, pero sí que deben existir en el servidor de producción. Si la estructura de directorios y archivos del proyecto miproyecto/ no los contiene, deben crearse manualmente.

16.5.4. Administrando una aplicación en producción

El comando más utilizado en los servidores de producción es cache:clear. Cada vez que se actualiza Symfony o el proyecto, se debe ejecutar esta tarea (por ejemplo después de ejecutar la tarea project:deploy) y también cada vez que se modifica la configuración en producción.

> php symfony cache:clear

Nota Si en el servidor de producción no está disponible la línea de comandos de Symfony, se puede borrar la cache manualmente borrando todos los contenidos del directorio cache/.

También es posible deshabilitar temporalmente la aplicación, por ejemplo cuando se necesita actualizar una librería o cuando se tiene que actualizar una gran cantidad de datos.

> php symfony project:disable NOMBRE_APLICACION NOMBRE_ENTORNO

Por defecto, una aplicación deshabilitada muestra la página sfConfig::get('sf_symfony_lib_dir')/exception/data/unavailable.php. No obstante, si creas una página llamada unavailable.php en el directorio config/ del proyecto, Symfony utiliza tu página en vez de la página predefinida.

La tarea project:enable vuelve a habilitar la aplicación y borra su cache.

> php symfony project:enable NOMBRE_APLICACION NOMBRE_ENTORNO

Nota La tarea project:disable no tiene ningún efecto a menos que la opción check_lock tenga un valor de on en el archivo de configuración settings.yml.