Tag Archives: linux

Publicar una Aplicación de DJango en un Contenedor Docker

Podemos estar tentados de pasar a producción el contenedor Docker con el runserver que proporciona el manager.py de DJango. Pero esto es un gravísimo error de seguridad. En la siguiente entrada explicaremos como crear el contenedor Docker con el módulo wsgi de Apache.

En la siguiente entrada veremos lo sencillo que es construir nuestra imagen para Docker de nuestra App de DJango con el Dockerfile que nos proporciona Graham Dumpleton.

Lo único que necesitamos es el código DJango de la aplicación (obviamente) y el fichero requirements.txt que debe estar en la raiz donde vamos a colocar nuestro Dockerfile.

Pongamos que nuestro requirements.txt tiene este aspecto:

numpy==1.6.2
Django==1.4.2
django-tastypie==0.9.14
pyes==0.19.1

Lo siguiente que necesitamos conocer es el dónde colocar los estáticos tanto la URL como la ubicación física en el directorio.

Lo típico es poner los estáticos bajo la URL /static/ y en el disco en el directorio static de nuestra aplicación. Debemos conocer estos datos para pasarlo al comando con el que arrancar la imagen.

Bien, como decíamos, partimos de la imagen siguiente

FROM grahamdumpleton/mod-wsgi-docker:python-2.7-onbuild

Usaremos onbuild porque tiene dos disparadores interesantes que nos simplifican muchísimo la vida. El primero copia el contenido del directorio actual a /app y el segundo ejecuta

pip install -r requirements.txt

Con el contenido de nuestro fichero de requirements.

La única línea que tenemos que añadir a nuestro Dockerfile sería la siguiente:

CMD ["--url-alias", "/static", "awesomeapp/static", "awesomeapp/wsgi.py"]

Y la construimos

# docker build -t awesomeapp-wsgi .

Ya podemos ponerla en producción sin riesgo.

# docker run -d -p 80:80 --name awesomeapp-pro awesomeapp-wsgi

Referencias:

  1. http://blog.dscpl.com.au/2014/12/hosting-python-wsgi-applications-using.html
  2. https://hub.docker.com/r/grahamdumpleton/mod-wsgi-docker/
  3. https://github.com/GrahamDumpleton/mod_wsgi-docker

Dos formas de mandar señales a procesos en Linux

Resulta que por temas de Copyright, no puedo usar el artículo publicado en The Geek Stuff (ver comentarios) así que como su contenido no es original y la temática me parece de conocimiento público, vamos a reescribirlo.

1. Enviar una señal a un proceso usando el comando kill.

Estando en consola, podemos enviar una señal a un proceso mediante el comando kill. Según Wikipedia:

En Unix y los sistemas operativos tipo Unix, kill es un comando utilizado para enviar mensajes sencillos a los procesos ejecutándose en el sistema.

Así si queremos mandar una señal a un proceso con el PID 1234 haríamos lo siguiente:

$ kill -s VALUE 1234

Las señales que le podemos mandar a un proceso son las siguientes (observar Value):

$ man 7 signal
[...]
Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
SIGCHLD   20,17,18    Ign     Child stopped or terminated
SIGCONT   19,18,25    Cont    Continue if stopped
SIGSTOP   17,19,23    Stop    Stop process
SIGTSTP   18,20,24    Stop    Stop typed at tty
SIGTTIN   21,21,26    Stop    tty input for background process
SIGTTOU   22,22,27    Stop    tty output for background process
[...]

2. Enviar la señal al proceso a través de otro proceso.

Para enviar señales a un proceso dentro de un programa C se emplea la siguiente llamada.

int kill(int pid, int sig);

La llamada al sistema kill toma dos argumentos:

  1. El PID (process ID, identificador de proceso) del proceso que tiene que ser “señalizado”.
  2. La señal que le enviaremos al proceso. kill devuelve 0 si todo ha ido bien, -1 si ha ocurrido algún error, se asignará el valor apropiado a errno

Vamos a verlo en un ejemplo de mis apuntes de Sistemas Operativos (3º Ingeniería Técnica de Sistemas):

//Envia al proceso con PID pasado como parámetro la señal SIGTERM
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
 
int main(int argc, char *argv[])
{
  if (argc != 2) {
    printf("Uso: %s pid\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  if (kill(atoi(argv[1]), SIGTERM) == -1) {
    perror("fallo en kill");
    exit(EXIT_FAILURE);
  }
}

Es una pena que no se suban al carro de compartir el conocimiento, es sólo una opinión, y hay que respetarla, pero es lo bueno de Internet, la posibilidad de intercambiar la información, no se trata de presentarla como obra tuya, si no de dar a conocer lo que cualquiera quiera, por eso, es de etiqueta, citar fuentes y referencias. En fin, que como decimos por aquí, “hay gente pa tó

No se carga .bashrc al iniciar sesión por SSH

Si iniciamos sesión en alguna máquina remota por ssh y vemos que no nos carga el fichero ~/.bashrc donde es más que probable que tengamos definida nuestra configuración favorita para la shell con un PS1 personalizado, un PATH más cómodo o algunos Alias útiles, es porque al iniciar sesión por ssh se lee el fichero ~/.bash_profile así, lo que debemos hacer es indicar en este fichero que utilice la configuración almacenada en ~/.bashrc.

 $ vim .bash_profile

Añadimos

if [ -f ~/.bashrc ]; then
  .  ~/.bashrc;
fi

Como vimos en alguna entrada anterior usar un . (PUNTO) es un alias del comando source que permite cargar la configuración almacenada en un archivo.

Paquetes non-free en Debian

Buscando por ahí me encontré con el siguiente comando.

vrms

Que muestra un listado de los paquetes non-free (no libres, codigo propietario, binarios cerrados, etc). En la página de manual, explican que es un intento de concienciar de lo “malo” que es el uso de este tipo de software en los sistemas GNU/Linux para empezar porque es una contradicción con el contrato social de Debian. Pero que es tolerado porque hace que algunas cosas funcionen… La página de manual está en inglés pero también los explican en la Wikipedia.

Aquí una captura del funcionamiento.

vrms

vrms

En mi caso de casi 2000 paquetes instalados sólo son propietarios el 0.05% que creo que es poco o muy poco.

Utilizando ficheros de configuración en los scripts de Bash

En algunas ocasiones tal vez necesites crear un script de Bash para resolver algunas tareas y que utilice un fichero de configuración. ¿Cómo lo plantearías? ¿Cómo implementarías el fichero de configuración?

Lo primero que pensé fue en utilizar el comando cut de forma que el fichero de configuración tuviera un formato de etiqueta=valor, y podría “cortar” para leer la etiqueta y el valor. Pero es mala cosa, porque por cada línea del fichero de configuración tienes que cortar y luego saber qué etiqueta es. La mejor solución, el comando source

Suponemos un fichero de configuración config.ini como este:

PATTERN="$hello*"
FILENAME=hello.txt
OUTPUT=result.txt

Y queremos que nuestro script lea estas variables y ejecute grep

#!/bin/bash
source config.ini

grep ${PATTERN} ${FILENAME} > ${OUTPUT}

El comando source importara todas las variables del fichero de configuración config.ini en nuestro script y prodremos utilizarlas para lanzar grep. También podemos sustituir el comando source por un . (un punto) así:

. config.ini

También podemos importar otros script con sentencias de control (if-else) pero hay que tener cuidado porque si el script que importamos contiene el comando exit el programa finalizará en ese punto. Por ejemplo, importamos el siguente trozo de código:

config.sh

#!/bin/bash
HELLO=world
exit

Y lo utilizamos en este:

parent.sh

#!/bin/bash
source config.sh
echo ${HELLO}

Cuando lanzamos el script ./parent.sh terminará antes de llegar a la línea de echo porque ha leído el exit

Espero que este pequeño truco os de una idea de como utilizar el comando source para importar fichero de configuración dentro de vuestros scripts

Es una traducción de este truco en linux.byexamples.com