4 Nov 2015
Alfonso Fernández
@alfonsofega
Alfonso Fernández
Responsable de I+D+i & Desarrollador & cofundador en Cloudman Labs
alfonso.fernandez@cloudmanlabs.com
Desarrollo de software en nube
$ git push heroku master
Código fuente
Dependencias
Procfile
Variables de entorno
Add-ons
pom.xml
Gemfile
package.json
composer.json
requirements.txt
Declara los procesos de nuestra aplicación
Fichero que se crea en la raíz de nuestro proyecto
Es un tipo especial
<process type>: <command>
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
$ heroku ps:scale worker=1
$ heroku ps:resize worker=standard-2x
Escalar dyno del proceso
Escalar proceso
Heroku provee un mecanismo de configuración de variables de entorno.
Principal diferencia entre entornos
(dev, staging, prod)
$ heroku config:set NAME=VALUE
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
$ git push heroku master
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 la aplicación que se desarrolla en el libro
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: *******
...
$ git clone https://github.com/afgar/Cupon.git
$ cd Cupon
$ heroku apps:create
$ git push heroku master
$ heroku open
$ heroku apps:create
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
# Si quieremos hacer deploy de otra rama
$ git push heroku <branch>:master
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
# 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.
"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
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
$ heroku config:set SECRET=c3fe8824310c1467432e0636c33b94354c1c91ac
# 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
{
"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
$ 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:
$ heroku addons:create cleardb:ignite
Sustituye al cron
Es escalable
"best effort"
$ heroku addons:create scheduler:standard
$ heroku logs --tail
¡Ya esta asi de simple! En nuestra console empezamos a ver los logs en streaming
$ 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
$ heroku releases
$ heroku rollback vXX
TODO LIST