Desplegando aplicaciones Symfony en Heroku
4 Nov 2015
Alfonso Fernández
Gracias ;)
@alfonsofega
About
Alfonso Fernández
Responsable de I+D+i & Desarrollador & cofundador en Cloudman Labs
alfonso.fernandez@cloudmanlabs.com
Desarrollo de software en nube
Parte 2
Desplegando una aplicación Symfony en Heroku
$ git push heroku master
Un poco de teoría...
¿Qué es una aplicacion para Heroku?
Código fuente
Dependencias
Procfile
Variables de entorno
Add-ons
Gestores de dependencias...
pom.xml
Gemfile
package.json
composer.json
requirements.txt
Procfile
Declara los procesos de nuestra aplicación
Fichero que se crea en la raíz de nuestro proyecto
Tipos de procesos
web
Es un tipo especial
<process type>: <command>
otros tipos
Podemos llamarlos como queramos, pero es común usar worker (para realizar tareas) y clock (para scheduled task) como nombre.
Lo mejor de todo es que los procesos se escalan independientemente
Escalabilidad de procesos
$ heroku ps:scale worker=1
$ heroku ps:resize worker=standard-2x
Escalar dyno del proceso
Escalar proceso
Variables de entorno
Heroku provee un mecanismo de configuración de variables de entorno.
Principal diferencia entre entornos
(dev, staging, prod)
$ heroku config:set NAME=VALUE
Add-ons
Son los servicios que usa la aplicación
Base de datos (MySQL)
Cola de mensajes (RabbitMQ)
Cache (Redis)
...
No estamos limitados a los add-ons
Podemos usar cualquier servicio de terceros como Amazon S3 o Amazon Cloudfront
¡Ya sabemos que es una aplicación para Heroku!
Desplegando en Heroku
$ git push heroku master
pero hay mas...
pero...
¿qué hace Heroku para que sea tan fácil desplegar?
¿Es magia?
Cuando sube el código fuente, heroku detecta el "package manager", lanza un build pack especifico para el lenguaje, obtiene las dependencias, crea los archivos necesarios y ejecuta los procesos definidos en el archivo Procfile
es prestidigitación
¡No!
Mucha teoría pero todavía no hemos visto ninguna aplicación...
¡Vamos a desplegar una aplicación Symfony en Heroku!
Aplicación de ejemplo
Fork de "Cupon"
Es la aplicación que se desarrolla en el libro
¿Que necesitamos?
Una cuenta en Heroku: https://signup.heroku.com/
Heroku toolbet: https://toolbelt.heroku.com/
$ heroku login
Enter your Heroku credentials.
Email: example@example.com
Password: *******
...
Vamos a desplegar la aplicación de ejemplo
$ git clone https://github.com/afgar/Cupon.git
$ cd Cupon
$ heroku apps:create
$ git push heroku master
$ heroku open
$ heroku apps:create
¿Que ha ocurrido?
Crea una aplicación Heroku en la region de USA, le establece un nombre aleatorio y añade el git remote heroku
$ heroku apps:create <nombre app> --remote <nombre git remote> --region <region eu|us>
# Ejemplo para crear una app en produccion en Europa
$ heroku apps:create myapp --remote prod --region eu
# Ejemplo para crear una app staging en Europa
$ heroku apps:create myapp-staging --remote staging --region eu
Tip
# Si quieremos hacer deploy de otra rama
$ git push heroku <branch>:master
Tip
¿Qué le has hecho a la aplicación?
Crear el archivo Procfile
Realmente no es necesario, symfony 2.7 tiene un comando que detecta heroku y autogenera el Profile cuando se esta desplegando la aplicación
# Con apache
web: bin/heroku-php-apache2 web/
# Con nginx
web: bin/heroku-php-nginx -C nginx_app.conf web/
{
# ...
"scripts": {
"post-install-cmd": [
# ...
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget",
# ...
],
"post-update-cmd": [
# ...
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget",
# ...
]
},
# ...
}
Archivo composer.json
/**
* Sets up deployment target specific features.
* Could be custom web server configs, boot command files etc.
*
* @param $event CommandEvent An instance
*/
public static function prepareDeploymentTarget(CommandEvent $event)
{
static::prepareDeploymentTargetHeroku($event);
}
protected static function prepareDeploymentTargetHeroku(CommandEvent $event)
{
$options = static::getOptions($event);
if (($stack = getenv('STACK')) && ($stack == 'cedar' || $stack == 'cedar-14')) {
$fs = new Filesystem();
if (!$fs->exists('Procfile')) {
$event->getIO()->write('Heroku deploy detected; creating default Procfile for "web" dyno');
$fs->dumpFile(
'Procfile',
sprintf('web: $(composer config bin-dir)/heroku-php-apache2 %s/',
$options['symfony-web-dir'])
);
}
}
}
Sensio\Bundle\DistributionBundle\Composer\ScriptHandler
Cambiar el destino de los log a stderr en producción
# app/config/config_prod.yml
monolog:
# ...
handlers:
# ...
nested:
# ...
path: "php://stderr" # antes "%kernel.logs_dir%/%kernel.environment%.log"
No queremos que nuestros log vayan a un fichero ya que el almacenamiento de las dynos es efímero y no se comparte.
Establecer como dependencia las extensiones PHP necesarias
"require": {
# ...
"ext-intl" : "*",
"ext-mbstring" : "*",
"ext-apcu" : "*", # Para cache de doctrine
# ...
},
Lista completa de extensiones que soporta Heroku
https://devcenter.heroku.com/articles/php-support#extensions
composer.json
$ heroku config:set SYMFONY_ENV=prod
Establecer la variable de entorno SYMFONY_ENV
Si no declaramos explicitamente en entorno en Symfony se ejecuta dev, lo que puede causar problemas. Para ello definimos la variable de entorno SYMFONY_ENV
¡No olvidemos el parámetro secret!
$ heroku config:set SECRET=c3fe8824310c1467432e0636c33b94354c1c91ac
Pasos built adiccionales
# composer.json
{
"scripts": {
"compile": [
"rm web/app_dev.php", # Elimina app_dev.php
"php app/console assetic:dump" # Ejecuta assetic:dump
]
}
}
Si queremos ejecutar pasos de compilaccion adiccionales durante la contruccion del programa no debemos utilizar post-install-cmd para ello tenemos el comando compile personalizado que ejecutará heroku
Configuraciones de la aplicación
{
"extra": {
"incenteev-parameters": {
"file": "app/config/parameters.yml",
"env-map": {
"database_url": "CLEARDB_DATABASE_URL",
"secret": "SECRET"
}
}
}
}
Deberemos mapear las variables de entorno a nuestras variables que necesitemos del archivo parameters.yml
Addons utilizados
Papertrail
$ heroku addons:create papertrail:choklad
Gestiona logs del sistema, dado que logplex solo emite un stream de logs.
Para mi es la mas simple
Nos permite:
- Ver los últimos mensajes
- Buscar en el log y guardar búsquedas
- Enviar alertas
- Automáticamente crea archivos de log comprimidos que son descargables o los envia a amazon S3.
ClearDB MySQL
$ heroku addons:create cleardb:ignite
- El servicio de MySQL más económico
- Es gratis hasta 5MB
- Backup diario automatico
Heroku Scheduler
Sustituye al cron
Es escalable
"best effort"
$ heroku addons:create scheduler:standard
Mantenimiento y gestión de la aplicación
Logs del sistema
$ heroku logs --tail
¡Ya esta asi de simple! En nuestra console empezamos a ver los logs en streaming
Quiero ejecutar comandos de Symfony
¿Cómo lo hago?
Para eso tenemos las one-off dynos!!
$ heroku run "php app/console doctrine:schema:create"
$ heroku run "php app/console doctrine:fixtures:load"
$ heroku run "php app/check.php"
$ heroku run bash
Rollback!
$ heroku releases
$ heroku rollback vXX
pero...
...queda trabajo pendiente
- Utilizar un servicio para enviar emails: mandrill, sendgrid, etc...
- Utilizar Amazon S3 como sistema de ficheros
TODO LIST
Conclusiones
¿Preguntas?
Desplegando aplicaciones Symfony en Heroku
By Alfonso Fernández
Desplegando aplicaciones Symfony en Heroku
Parte 2. ¿Cómo desplegar una aplicación Symfony en Heroku?
- 5,342