deployment template - Despliegue de Django con gunicornio y nginx




tags templates (5)

Esta es una pregunta amplia, pero me gustaría obtener una respuesta canónica. He estado intentando implementar un sitio usando gunicorn y nginx en Django . Después de leer toneladas de tutoriales, he tenido éxito, pero no puedo estar seguro de que los pasos que seguí sean lo suficientemente buenos como para ejecutar un sitio sin problemas o tal vez haya mejores formas de hacerlo. Esa incertidumbre es molesta.

Es por eso que estoy buscando una respuesta muy detallada y bien explicada para los novatos. No quiero explicar demasiado lo que sé y lo que no sé, ya que esto podría sesgar un poco las respuestas y otras personas podrían beneficiarse en menor grado de sus respuestas. Sin embargo, algunas cosas que me gustaría ver mencionadas son:

  • ¿Qué "configuración" has visto que funciona mejor? Usé virtualenv y moví mi proyecto Django dentro de este entorno, sin embargo, he visto otras configuraciones donde hay una carpeta para entornos virtuales y otra para proyectos.

  • ¿Cómo puedo configurar las cosas de una manera que permita alojar varios sitios en un único servidor?

  • ¿Por qué algunas personas sugieren usar gunicorn_django -b 0.0.0.0:8000 y otros sugieren gunicorn_django -b 127.0.0.1:8000 ? Probé esta última en una instancia de Amazon EC2 pero no funcionó mientras que la primera funcionó sin problemas.

  • ¿Cuál es la lógica detrás del archivo de configuración de nginx? Hay tantos tutoriales que usan archivos de configuración drásticamente diferentes que estoy confundido sobre cuál es mejor. Por ejemplo, algunas personas usan alias /path/to/static/folder y otras root /path/to/static/folder . Tal vez puedas compartir tu archivo de configuración preferido.

  • ¿Por qué creamos un enlace simbólico entre site-available y sites-enabled en /etc/nginx ?

  • Algunas de las mejores prácticas son como siempre bienvenidas :-)

Gracias


Answers

¿Qué "configuración" has visto que funciona mejor? Usé virtualenv y moví mi proyecto django dentro de este entorno, sin embargo, he visto otras configuraciones donde hay una carpeta para entornos virtuales y otra para proyectos.

virtualenv es una forma de aislar los entornos de Python; como tal, no tiene una gran parte en la implementación , sin embargo, durante el desarrollo y las pruebas es un requisito, si no muy recomendable.

El valor que obtendría de virtualenv es que le permite asegurarse de que se instalen las versiones correctas de las bibliotecas para la aplicación. Por lo tanto, no importa dónde se pegue el envolvimiento virtual en sí mismo. Solo asegúrate de no incluirlo como parte del sistema de control de versiones del código fuente.

El diseño del sistema de archivos no es crítico. Verá muchos artículos que exaltan las virtudes de los diseños de directorios e incluso los esqueletos de proyectos que puede clonar como punto de partida. Siento que esto es más una preferencia personal que un requisito difícil. Claro, es bueno tenerlo; pero a menos que sepa por qué , no agrega ningún valor a su proceso de implementación, por lo tanto, no lo haga porque algunos blogs lo recomiendan a menos que tenga sentido para su escenario. Por ejemplo, no es necesario crear un archivo setup.py si no tiene un servidor PyPi privado que sea parte de su flujo de trabajo de implementación.

¿Cómo puedo configurar las cosas de una manera que permita alojar varios sitios en un único servidor?

Hay dos cosas que necesita para hacer configuraciones de sitios múltiples:

  1. Un servidor que está escuchando en la IP pública en el puerto 80 y / o en el puerto 443 si tiene SSL.
  2. Un grupo de "procesos" que ejecutan el código fuente real de django.

La gente usa nginx para # 1 porque es un proxy muy rápido y no viene con la sobrecarga de un servidor completo como Apache. Usted es libre de usar Apache si se siente cómodo con él. No existe el requisito de que "para varios sitios use nginx"; solo necesita un servicio que esté escuchando en ese puerto, sepa cómo redirigir (proxy) a sus procesos que ejecutan el código de django real.

Para el # 2 hay algunas maneras de comenzar estos procesos. gevent / uwsgi son los más populares. Lo único que debe recordar aquí es no usar runserver en producción .

Esos son los requisitos mínimos absolutos. Normalmente, las personas agregan algún tipo de administrador de procesos para controlar todos los "servidores django" (# 2) en ejecución. Aquí verá upstart y el docs mencionado. Prefiero el supervisor, ya que no necesita hacerse cargo de todo el sistema (a diferencia del advenedizo). Sin embargo, nuevamente, este no es un requisito difícil . Podría ejecutar perfectamente un montón de sesiones de screen y separarlas. La desventaja es que, si tu servidor se reinicia, tendrías que reiniciar las sesiones de la pantalla.

Personalmente, recomendaría:

  1. Nginx para el n. ° 1
  2. Elija entre uwsgi y gunicorn - Utilizo uwsgi.
  3. docs para administrar los procesos de back-end.
  4. Cuentas de sistema individuales (usuarios) para cada aplicación que está hospedando.

La razón por la que recomiendo el número 4 es para aislar los permisos; de nuevo, no es un requisito.

¿Por qué algunas personas sugieren usar gunicorn_django -b 0.0.0.0:8000 y otros sugieren gunicorn_django -b 127.0.0.1:8000? Probé esta última en una instancia de Amazon EC2 pero no funcionó mientras que la primera funcionó sin problemas.

0.0.0.0 significa "todas las direcciones IP", es una meta dirección (es decir, una dirección de marcador de posición). 127.0.0.1 es una dirección reservada que siempre apunta a la máquina local. Es por eso que se llama "localhost". Solo se puede acceder a los procesos que se ejecutan en el mismo sistema.

Normalmente tiene el servidor front-end (n. ° 1 en la lista anterior) escuchando en la dirección IP pública. Debería vincular explícitamente el servidor a una dirección IP .

Sin embargo, si por algún motivo está en DHCP o no sabe cuál será la dirección IP (por ejemplo, es un sistema recién aprovisionado), puede indicar a nginx / apache / cualquier otro proceso que se vincule a 0.0.0.0 . Esto debería ser una medida provisional de pausa .

Para los servidores de producción, tendrá una IP estática. Si tiene una dirección IP dinámica (DHCP), puede salir en 0.0.0.0 . Sin embargo, es muy raro que tengas DHCP para tus máquinas de producción.

No se recomienda encuadernar gunicorn / uwsgi a esta dirección en producción. Si enlaza su proceso backend (gunicorn / uwsgi) a 0.0.0.0 , puede ser accesible "directamente", evitando su proxy front-end (nginx / apache / etc); alguien podría simplemente solicitar http://your.public.ip.address:9000/ y acceder a su aplicación directamente, especialmente si su servidor de aplicaciones para el usuario (nginx) y su proceso de back-end (django / uwsgi / gevent) se están ejecutando en el mismo máquina .

Sin embargo, puede hacerlo si no desea tener la molestia de ejecutar un servidor proxy front-end.

¿Cuál es la lógica detrás del archivo de configuración de nginx? Hay tantos tutoriales que usan archivos de configuración drásticamente diferentes que estoy confundido sobre cuál es mejor. Por ejemplo, algunas personas usan "alias / ruta / a / static / carpeta" y otras "raíz / ruta / a / estática / carpeta". Tal vez puedas compartir tu archivo de configuración preferido.

Lo primero que debes saber sobre nginx es que no es un servidor web como Apache o IIS. Es un proxy. Por lo tanto, verá diferentes términos definidos como 'ascendente' / 'descendente' y múltiples 'servidores'. Tómese su tiempo y revise primero el manual de nginx.

Hay muchas formas diferentes de configurar nginx; pero aquí hay una respuesta a tu pregunta sobre alias vs. root . root es una directiva explícita que vincula la raíz del documento (el "directorio de inicio") de nginx. Este es el directorio que verá cuando entregue una solicitud sin una ruta como http://www.example.com/

alias significa "asignar un nombre a un directorio". Los directorios con alias no pueden ser un subdirectorio de la raíz del documento.

¿Por qué creamos un enlace simbólico entre sitios disponibles y sitios habilitados en / etc / nginx?

Esto es algo exclusivo de Debian (y de sistemas similares a Debian como Ubuntu). sites-available enumera los archivos de configuración para todos los hosts / sitios virtuales en el sistema. Un enlace simbólico desde sites-enabled a sites-available "activa" ese sitio o servidor virtual. Es una forma de separar los archivos de configuración y habilitar / deshabilitar fácilmente los hosts.



Bueno, en lo que respecta a las mejores prácticas que ha preguntado en su pregunta, ¡no puedo evitar compartir una herramienta que funcionó de maravillas para mí, literalmente! Yo mismo solía confundirme en varios archivos de configuración de gunicorn, nginx, supervisorD para varios sitios. Pero ansiaba de alguna manera automatizar todo el proceso para poder hacer cambios en mi aplicación / sitio y desplegarlo al instante. Su nombre es django-fagungis. Aquí puede encontrar detalles de mi experiencia con la automatización de implementación Django . Acabo de configurar un fabfile.py ONCE (django-fagungis usa fabric para automatizar todo el proceso y crea virtualenv en su servidor remoto, que es MUY útil para administrar dependencias de varios sitios alojados en un solo servidor. Utiliza nginx, gunicorn y supervisorD manejar el proyecto Django / implementación del sitio) y django-fagungis clona mi último proyecto de bitbucket (que uso para la subversión) y lo despliega en mi servidor remoto y solo tengo que ingresar tres comandos en el shell de mi máquina local y que !! Para mí, esta ha resultado ser la mejor y más libre práctica para el despliegue de Django.


No soy un gurú de implementación, pero compartiré algunas de mis prácticas para implementar Django con gevent (aunque debería ser similar a gunicorn).

virtualenv es genial por razones que no entraré. Sin embargo, encontré que virtualenv-wrapper ( docs ) es muy útil, especialmente cuando trabajas en muchos proyectos, ya que permite cambiar fácilmente entre los diferentes virtualenvs. Esto realmente no se aplica al entorno de despliegue; sin embargo, cuando necesito solucionar problemas en el servidor usando SSH, esto me pareció muy útil. Otra ventaja de usarlo es que administra el directorio virtualenv, por lo tanto, menos trabajo manual para usted. Los Virtualenvs están destinados a ser desechables, de modo que en caso de que tenga problemas de versión o cualquier otro problema de instalación, puede simplemente volcar el entorno y crear uno nuevo. Como resultado, es una buena práctica no incluir ninguno de los códigos de su proyecto dentro del virtualenv. Debe mantenerse separado.

En cuanto a la configuración de múltiples sitios, virtualenv es más o menos la respuesta. Debe tener un virutalenv por separado para cada proyecto. Solo eso puede resolver muchos problemas. Luego, cuando implemente, un proceso de Python diferente ejecutará diferentes sitios, lo que evita cualquier posible conflicto entre las implementaciones. Una herramienta que particularmente encontré muy útil en la administración de múltiples sitios en el mismo servidor es supervisor ( docs ). Proporciona una interfaz sencilla para iniciar, detener y reiniciar diferentes instancias de Django. También es capaz de reiniciar automáticamente un proceso cuando falla o cuando la computadora se inicia. Entonces, por ejemplo, si se levanta una excepción y nada lo atrapa, todo el sitio web puede caer. El supervisor lo detectará y reiniciará automáticamente la instancia de Django. La siguiente es una configuración del programa supervisor de ejemplo (un solo proceso):

[program:foo]
command=/path/toviertualenv/bin/python deploy.py
directory=/path/where/deploy.py/is/located/
autostart=true
autorestart=true
redirect_stderr=True
user=www

Para Nginx, sé que puede ser abrumador al principio. Encontré el book Nginx muy útil. Explica todas las principales directivas nginx.

En mi instalación de nginx, encontré que la mejor práctica es configurar solo las configuraciones centrales en el archivo nginx.conf y luego tengo una carpeta separada de sites donde guardo las configuraciones nginx para cada uno de los sitios que tengo. Luego solo incluyo todos los archivos de esa carpeta en el archivo de configuración central. Uso la directiva include sites/+*.conf; . De esta forma, solo incluye los archivos que comienzan con el símbolo + dentro de la carpeta de sites . De esta forma, solo con el nombre de archivo puedo controlar qué archivos de configuración se cargarán. Entonces, si deseo desactivar un determinado sitio, solo tengo que cambiar el nombre del archivo de configuración y reiniciar nginx. No estoy muy seguro de lo que quiere decir con "enlace simbólico entre sitios disponibles y sitios habilitados en / etc / nginx" en su pregunta, ya que son carpetas con el nombre Apache pero cumplen una tarea similar a la directiva include .

En cuanto a root directivas de root y alias , son prácticamente iguales, excepto cuando se calcula su raíz. En alias , lo que sea en la location en dropeado, mientras que en la raíz en no. Imagen de que tienes la siguiente configuración de nginx:

location /static {
    alias /some/path/;
}
location /static2 {
    root /some/other/path/;
}

Si el usuario va a estas URL, entonces nginx intentará buscar los archivos en los siguientes lugares del sistema:

/static/hello/world.pdf => /some/path/hello/world.pdf
/static2/hello/world.pdf => /some/other/path/static2/hello/world.pdf

Esta es una configuración simple para el sitio nginx:

server {
    server_name .foodomain.com;
    listen 80;

    access_log logs/foodomain.log;

    gzip                on;
    gzip_http_version   1.0;
    gzip_comp_level     2;
    gzip_proxied        any;
    gzip_min_length     1100;
    gzip_buffers        16 8k;
    gzip_types          text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    # Some version of IE 6 don't handle compression well on some mime-types, so just disable for them
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    # Set a vary header so downstream proxies don't send cached gzipped content to IE6
    gzip_vary on;

    location / {
        proxy_read_timeout      30s;
        proxy_pass              http://localhost:8000;
        proxy_set_header        Host                 $host;
        proxy_set_header        User-Agent           $http_user_agent;
        proxy_set_header        X-Real-IP            $remote_addr;
    }

    location /media {
        alias   /path/to/media/;
        expires 1y;
    }

    location /static {
        autoindex on;
        expires   1y;
        alias     /path/to/static/;
    }

     location /favicon.ico {
        alias /path/to/favicon.ico;
    }
}

Espero que esto te ayude un poco.


También puede usar jQuery de la siguiente manera:

 $(document).ready(function(){
    $("textarea").attr({"rows": "4",
                        "cols": "15"
    });
});




django deployment nginx setup-deployment gunicorn