lunes, 25 de noviembre de 2013

Puesta en producción de una aplicación web con Django y Nginx


Cuando se usan frameworks para desarrollo web todo se hace más fácil, excepto la puesta en producción, una muestra clara de esto es django, un framework que permite que cosas como hacer un entorno de administración parezca juego de niños y que realizar consultas que parecen concebidas en la maligna mente del mismo Satanás sea una tarde de picnic. Desafortunadamente a la hora de poner en producción un proyecto empezamos a ver dificultades. Este post tiene como objetivo mostrar una sencilla manera de poner en producción nuestros proyectos con Django mediante el servidor Nginx.

Nota: Todo el proceso de configuración esta preparado para Linux Debian y derivados, si usas una distribución diferente es probable que cambien las rutas de los archivos de configuración.

Primero que todo, ¿Qué es Nginx?

Nginx es un servidor web y proxy inverso ligero de muy alto rendimiento, es software libre de código abierto y multiplataforma, tiene las siguientes características:
  • Servidor de archivos estáticos, índices y autoindexado.
  • Proxy inverso con opciones de caché.
  • Permite realizar balanceo de carga.
  • Tolerancia a fallos.
  • Soporte de HTTP sobre SSL.
  • Soporte para FastCGI con opciones de caché.
  • Servidores virtuales basados en nombre y/o en dirección IP.
  • Streaming de archivos FLV y MP4.
  • Soporte para autenticación.
  • Compatible con IPv6.
  • Soporte para protocolo SPDY.
  • Soporte para compresión gzip de paquetes.
  • Habilitado para soportar más de 10.000 conexiones simultáneas.
Muy bien, pero ¿Qué pasa con lo clásico?
Muchos se preguntaran ¿Por qué Nginx y no Apache2?, pienso que hay varias cosas al respecto:
  • La cantidad de recursos que demanda Apache2 son mucho mayores que los demandados por Nginx.
  • La velocidad alcanzada por Nginx es mucho mayor que la de Apache2 a la hora de responder peticiones.
  • Nginx es muchisimo más fácil de configurar que Apache2 puesto que Apache2 usa engorrosos XMLs, Nginx no.
La información mencionada la obtuve de aquí, aquí y aquí.

Muy bien, entonces, manos a la obra
En este momento me parece adecuado explicar cómo funciona la conexión entre django y Nginx:

Nginx es el encargado de atender las peticiones externas por el puerto 80 (protocolo HTTP), éste a su vez envía los datos de la petición a uWSGI mediante un puerto auxiliar, quien hace de intermediario en el proceso de comunicación y finalmente uWSGI entrega los datos de petición a nuestro proyecto django para que éste ejecute la acción correspondiente e inicie el proceso inverso para responder a la petición. Escogí uWSGI porque me pareció muy fácil de usar y en éste enlace hay una comparativa de rendimiento en la cual el tiempo de respuesta es mejor que el de Gunicorn.

Configuremos Nginx
Debemos crear el archivo de configuración para nuestro proyecto, recuerda que si el puerto 80 está siendo usado por Apache2, por alguna otra aplicación o por el mismo Nginx por otra configuración debes liberar primero el puerto, en caso de ser Apache2 debes editar el archivo /etc/apache2/ports.conf y cambiar el puerto 80 por uno diferente, luego reiniciar el servicio Apache2 así:
$ service apache2 restart
Después de esto debes crear el archivo de configuración en la carpeta /etc/nginx/sites-avaliable, el nombre del archivo lo eliges tú, yo elegí como nombre archivo.conf. El contenido del archivo debe ser el siguiente:
# archivo.conf
server {
    listen      80; # puerto por el que escucha la aplicación
    server_name midominio.co; # nombre o ip del servidor
    charset     utf-8;

    # tamaño maximo de subida
    client_max_body_size 75M;

    # Ruta de la carpeta media
    location /media  {
        alias /var/www/proyecto/media; # reemplace por su ruta a media
    }

    # Ruta de la carpeta static
    location /static {
        alias /var/www/proyecto/static; # reemplace por su ruta a media
    }

    # Configuración de las peticiones que no son resueltas con las
    # reglas anteriores. Estas son reenviadas al servidor django
    location / {
        uwsgi_pass 127.0.0.1:8001; # 127.0.0.1:PUERTO_AUXILIAR
        include     uwsgi_params;
    }
}
Cabe resaltar que el puerto auxiliar seleccionado es el 8001, este dato es importante puesto que debemos tenerlo en cuenta para iniciar la labor de uWSGI.
Después de esto es necesario habilitar la nueva configuración creando un enlace simbólico del archivo en la carpeta sites-avaliable de Nginx así:
$ cd /etc/nginx/sites-enabled
$ ln -s ../sites-avaliable/archivo.conf .
Finalmente reiniciamos el servidor Nginx
$ service nginx restart

Configuremos nuestro entorno
Primero es necesario crear un entorno para el proyecto con la orden mkvirtualenv vista en el post anterior y luego activamos el entorno creado con la orden workon:
$ mkvirtualenv entorno
$ workon entorno
después de ésto es necesario instalar las dependencias de nuestro proyecto django, personalmente pienso que es bueno trabajar con django 1.5 o superior, puesto que aasi tendremos muchas de las nuevas características, además django 1.6 fue liberado hace un par de semanas.
$ pip install django
$ pip install ....
$ pip install ....
Ahora necesitamos instalar uWSGI:
$ pip install uwsgi
Nota: Para instalar uWSGI es necesario tener instalados en el sistema el compilador gcc y los paquetes de desarrollo de python, para el caso de linux debian y derivados con python2.7 deben instalarse como superusuario así:
$ apt-get install gcc-4.5 python2.7-dev
Finalmente creamos el archivo para iniciar el proceso de conexión entre Nginx y django, este archivo es un script bash al que yo llame start.sh, este debe tener el siguiente contenido:
#!/bin/bash
uwsgi --socket :8001 --wsgi-file wsgi.py -d mensajes.log

Aquí viene la parte importante, cuando django genera un proyecto él crea una carpeta de proyecto, dentro de ésta hay una carpeta con los archivos de configuración, éstos son settings.py, urls.py, __init__.py y wsgi.py


debe hacer una copia del archivo wsgi.py a la raíz del proyecto y en éste mismo lugar poner el archivo start.sh así:

Después es necesario permitir la ejecución de este archivo mediante la orden:
$ chmod +x start.sh
Luego podemos iniciar el proceso así:
$ ./start.sh
Si tienes alguna duda o comentario puedes hacerla en la sección de comentarios, espero que sea útil.

Si te gusto el post
compartelo... :D

sábado, 23 de noviembre de 2013

Virtualenv II, yendo más allá con virtualenvwrapper


En una entrada anterior vimos algo de Virtualenv, ahora vamos a ver cómo usar una herramienta que facilita un tanto su uso, Virtualenvwraper.

¿Qué es Virtualenvwrapper?
Virtualenvwrapper es un conjunto de herramientas para extender Virtualenv. Éstas herramientas incluyen wrappers o contenedores para la creación y eliminación de entornos virtuales y la gestión del flujo de trabajo para desarrollo, facilitando trabajar en más de un proyecto a la vez sin generar conflictos entre dependencias.

Características de Virtualenvwrapper
  • Organiza todos sus entornos virtuales en un solo lugar.
  • Wrappers para la gestión de sus entornos virtuales (crear, borrar, copiar).
  • Facilita cambiar entre entornos con un solo comando.
  • Implementa el uso de la tecla de tabulación (tab) para los argumentos de las ordenes de los entornos virtuales (no válido para el CMD de Windows, para esto es necesario tener una shell Cygwin).
  • Posibilidad para que el usuario cree hooks (ganchos) en todas las operaciones para ejecutar acciones propias. 
  • Sistema de plug-ins para la creación de extensiones.
Instalación
Luego de tener instalado Virtualenv instalamos Virtualenvwrapper mediante la orden
easy_install virtualenvwrapper
o
pip install virtualenvwrapper
Luego de esto es necesario configurarlo, para esto debemos seleccionar la carpeta en la cual quedarán almacenados los entornos, para este caso la carpeta de entornos quedará en el directorio del usuaio y se llamará .entornos (Para los sistemas *nix el punto al principio oculta los entornos) .  Entonces debemos establecer una variable al sistema (para Windows también es necesario agregar una ruta al path del sistema), esto se hace así:

Para sistemas *nix (Linux, MacOSX)
Buscar un archivo en la carpeta de usuario llamado .bashrc o .bash_profile, ábrelo con tu editor preferido y pones las siguientes líneas:
export WORKON_HOME=$HOME/.entornos
source /usr/local/bin/virtualenvwrapper.sh
En estas dos líneas lo que hacemos es definir cuál es el directorio donde vamos a guardar los entornos y en la que sigue estamos ejecutando el script de inicialización de virtualenvwrapper. Recuerda que podrías poner cualquier ruta del sistema por ejemplo:
export WORKON_HOME=/tmp/entornos
o
export WORKON_HOME=/home/andres/proyectos/entornos
Después de esto es necesario recargar las variables de entorno, si editamos el archivo .bashrc lo hacemos así:
source ~/.bashrc
si editamos el archivo .bash_history lo hacemos así:
source ~/.bash_history
Nota: También podrías simplemente cerrar y reabrir la consola, así se recargaría automáticamente.

Para Sistemas Windows:
Después de tener instalado Virtualenv en Windows (recuerda el post anterior) debes instalar desde la linea de comandos (CMD) virtualenvwrapper mediante la orden:
pip install virtualenvwrapper-win
después debes crear la carpeta para los entornos así:
mkdir %USERPROFILE%\entornos
y luego debes establecer las variables en el entorno así:
  • Entra al menú de propiedades:
    • Accede al menú de Inicio, click derecho al botón Equipo, y click al botón de propiedades.
    • Click al botón de configuración avanzada del sistema.
    • Click a el botón variables de entorno.
    • En la sección de Variables de entorno agregamos una variable llamada WORKON_HOME con el valor %USERPROFILE%\entornos.
La próxima vez que abramos una consola ya podremos usar virtualenvwrapper.

Nota: Si estás en Windows debes instalar virtualenvwrapper-win y si quieres y tienes Powershell virtualenvwrapper-powershell porque el paquete virtualenvwrapper es exclusivo de sistemas *nix.

Nota: El paquete virtualenvwrapper-win tiene como ruta por defecto de los entornos la carpeta %USERPROFILE%\Envs, por tanto si quieres obviar la configuración de la variable de entorno podrías hacerlo.

Nota: En ocasiones la instalación de virtualenvwrapper-win mediante pip no establece los ejecutables necesarios en la carpeta de scripts de python, por lo cual deberá instalarse descargando el código fuente mediante Git así:
git clone git://github.com/davidmarble/virtualenvwrapper-win.git
cd virtualenvwrapper-win
python setup.py install

Nota: es probable que al usar la orden mkvirtualenv salga el mensaje:
"El sistema no puede encontrar la ruta especificada."
no te preocupes por eso, el entorno se crea de todas maneras.


Modo de empleo:
Para crear entornos nuevos usamos:
mkvirtualenv <entorno> # entorno estandar
mkvirtualenv <entorno1> --no-site-packages # entorno totalmente aislado
Para activar el entorno:
workon <entorno>
Para desactivarlo:
deactivate
Para listar los entornos existentes:
lsvirtualenv
Para eliminar un entorno (recuerde que no puede estar usándolo en el momento de eliminarlo)
rmvirtualenv <entorno>
Para copiar un entorno:
cpvirtualenv <entorno> <nombre-copia>
Para ejecutar un comando en todos los entornos:
allvirtualenv <comando>
# un ejemplo sería:
allvirtualenv pip install django
Este es un listado de comandos básicos para la gestión de entornos y en este enlace queda la documentación de los comando de virtualenvwrapper.

Espero que les sirva de ayuda.
Si te gusto el post
compartelo... :D

jueves, 21 de noviembre de 2013

Git, qué, por qué y cómo


Carpetas, carpetas y más carpetas, eso es lo que uno encuentra en su disco duro cuando aún se es joven en el mundo de la informática ( todos lo hemos sido y en lo personal yo aún me siento así), pero es algo que todos empezamos a mejorar, clasificando la información de mejor manera y usando herramientas para esto. Los desarrolladores de software no son la excepción a esta regla, pero los problemas son un tanto más complejos ahora, puesto que no es solo guardar las carpetas con cientos o miles de líneas, además deben poder usarse comentarios específicos de cada carpeta o archivo, sin contar el hecho de que en cualquier momento podría fallar el disco duro y todo el trabajo se iría al mismísimo infierno (y muchos desarrolladores también pues sus jefes los deportarían). Para solucionar esto se crearon sistemas de control de versiones, en esta ocasión vamos a hablar de uno algo reciente pero muy potente, Git.

¿Qué es Git?
Git es un sistema de control de versiones distribuido, creado por Linus Torvalds con el fin de obtener la mayor eficiencia y la mejor confiabilidad posible. Se dice que es distribuido porque a diferencia de otros como SVN no hay un repositorio central contra el cual otros cargan y descargan actualizaciones,  por el contrario hay múltiples repositorios, unos se configuran como maestros y otros como esclavos y existe la posibilidad de cambiar la configuración en cualquier momento.

svn
Sistema de versiones Centralizado


git
Sistema de versiones distribuido
Como vemos en el gráfico 1 en sistemas centralizados de control de versiones como SVN todas las máquinas se sincronizan con una única máquina servidor, por el contrario en sistemas distribuidos como GIT cada una de las máquinas se pueden sincronizar con otras, y a su vez cada una de estas puede ser el repositorio maestro de otras.

Cuando existe un repositorio Git este tiene un repositorio local, el cual puede tener varias versiones de nuestro proyecto, a esto se le conocen como ramas (branches), de esta manera en un proyecto puede haber una rama estable, una de pruebas, una de desarrollo y demás.

¿Por qué?
Si quieres motivos para usar Git aquí los tienes:
  • Es distribuido. Gracias a esto obtienes:
    • Independencia. Tú eres un repositorio, no necesitas ninguna información de ningún otro lugar para ninguna operación. Es decir, no necesitas para nada red.
    • Mejor integración y comunicación en grupos de desarrollo grandes, de esta manera cada desarrollador puede compartir cambios con el resto sin depender de un servidor central.
  • Rapidez: Una de las principales características de Git es la velocidad que tiene para hacer todo lo que hace.
    • Manejo simple e intuitivo de las ramas de desarrollo:
    • Git permite mezclar varias ramas a la vez en una tercera (merge octopus).
    • Git permite mezclar eficientemente ramas que tenían como punto en común es un antiguo padre.
  • Git guarda contenido, más no ficheros, esto permite mayor eficiencia la hora de almacenar cambios pero obliga a que en el repositorio no hayan carpetas vacías (no tiene contenido alguno).
  • Permite trabajar en un punto intermedio entre nuestros ficheros reales y el repositorio, lo cual permite hacer modificaciones y más antes de que los cambios sean replicados.
  • Soporta múltiples protocolos de conexión a la hora de hacer publicación (HTTP, FTP, SSH, rsync).
  • Es compatible con otros sistemas de versiones como CVS y SVN.
  • Podrías pagar  por un servidor exclusivo para un proyecto y este te daría información relevante acerca del ritmo de trabajo, Github
¿Cómo?
A continuación pondré una lista de comando que pueden ser muy útiles.

Inicializar Repositorio
$ git init .
Agregar archivos
$ git add <file>
$ git add .
Actualizar archivos modificados
$ git add -u
Crear revisión inicial | Crear nueva revisión
$ git commit -m "mensaje de revisión"
Listar cambios realizados
$ git status
Listar los cambios del formato de parche
$ git diff
Ver historial de cambios
$ git log
$ git log -nX   #=> muestra las ultimas X revisiones
$ git log --stat --summary
Descartar todos los cambios hechos desde la última revisión
$ git reset --hard
Cargar archivo desde la última revisión
$ git checkout 
Corregir descripcion del último commit
$ git commit --amend
Incluir algo que faltó en la última revisión
$ git reset --soft HEAD^
$ git add arch1 arch2 ...
$ git commit
Crear un clon de un repositorio remoto
$ git clone <url del repositorio>
# por ejemplo
git clone ssh://usuario@mi.servidor.algo/ruta/interna/del/repositorio
Agregar origen remoto
$ git remote add origin <url del repositorio>
Sincronizar cambios con el repositorio remoto
$ git push origin master
Configurar usuario y correo para tener información de los commits
$ git config --global user.email "you@example.com"
$ git config --global user.name "Your Name"
Actualizar repositorio local
$ git pull origin master

Mostrar mensajes a color
$ git config --global color.ui auto
Evitar que nuestro servidor rachase commits externos
! [remote rejected] master -> master (branch is currently checked out)
$ git config receive.denyCurrentBranch ignore


Espero que les sirva de ayuda.

Si te gusto el post
compartelo... :D

martes, 19 de noviembre de 2013

Virtualenv, qué, por qué y cómo.


Cuando alguien empieza en el mundo de python lo que hace es crear sus programas e instalar librerías indiscriminadamente, sin tener en cuenta que puede que más adelante tenga conflictos a causa de las versiones de las librerías necesarias para sus proyecto. Es aquí donde Virtualenv salva el día.



¿Qué es Virtualenv?:
Virtualenv es una herramienta para crear entornos de python aislados, es decir entornos donde las librerías o las versiones de python no interfieren con las carpetas que python tiene por defecto en la maáquina. Haciendo una analogía con un edificio, un entorno vendría siendo como una planta, usa ciertos recursos como el agua o la energía eléctrica (para el caso de python usa la misma máquina) y a su vez cada planta tiene sus propios recursos, tales como los muebles, las habitaciones y demás (para el caso de python hablamos de librerías.).

¿Por qué?:
Cuando tienes python en tu máquina probablemente debas usar django 1.5 para un proyecto que surgio hace tiempo, y django1.6 para poder usar nuevas funciones, por esto es necesario usar Virtualenv, porque con ésta herramienta puedes crear espacios de trabajo separados con diferentes librerías o diferentes versiones de las mismas.

¿Cómo?:
Instalación:
primero debes tener python, luego instalas setuptools para poder usar easy_install, con easy_install instalas pip mediante la orden
easy install pip
y finalmente con pip instalas virtualenv
pip install virtualenv

nota: si usas Windows deberías agregar la carpeta de scripts de Python al path del sistema para poder usarlo desde la línea de comandos, mira este enlace.

Modo de empleo:

  • Crear un entorno 
    • virtualenv nombre_del_entorno 
  • Crear un entorno totalmente aislado virtualenv --no-site-packages nombre_del_entorno 
  • Usar un entorno especifico:
    • Hay que tener en cuenta que si es windows se hace de una manera un tanto diferente, puesto que en la carpeta del entono el genera una subcarpeta llamada Scripts y ahí está ubicado un archivo llamado activate.bat, mediante este se activa el entorno, entonces:
      • Para Windows (mediante la linea de comandos):
        • C:\.....\carpeta> ruta\a\la\carpeta\del\entorno\Scripts\activate.bat 
      • Para *nix [Mac, Linux] (desde la consola):
        • source /ruta/a/la/carpeta/del/entono/bin/activate 
    • nota: si el entorno quedo bien activado al principio de la linea de la consola debe aparecer entre parentesis el nombre del entorno, mas o menos así: 
      • (entorno)ogranada@maquina:~/python$ 
  • Para buscar paquetes 
    • pip search 
  • Instalar un paquete 
    • pip install paquete 
  • Eliminar paquete 
    • pip uninstall paquete 
  • Listar paquetes instalados (sirve para replicar el entono) 
    • solo listar 
      • pip freeze 
    • hacer archivo para replicar entorno 
      • pip freeze > requirements.txt 
  • Salir del entorno
    • deactivate



Espero que les sirva de ayuda.

Si te gusto el post
compartelo... :D