Docker es una plataforma abierta para construir, enviar y ejecutar aplicaciones distribuidas. Brinda a los programadores, equipos de desarrollo e ingenieros de operaciones la caja de herramientas común que necesitan para aprovechar la naturaleza distribuida y en red de las aplicaciones modernas.

logo

La contenedorización ofrece varias ventajas, como un aprovisionamiento más rápido o entornos aislados y fáciles de recrear. Si no sabe qué es la contenedorización, puede pensar en ella como una forma simplificada de virtualización. O mejor aún, puede buscar una descripción detallada, que no es el propósito de esta publicación.

Por un tiempo, he estado interesado en “Dockerizar” mis aplicaciones de Django para mejorar mis canalizaciones de implementación. Si bien la documentación en Docker es muy buena, sus ejemplos son demasiado generales para mí, así que decidí investigar un poco sobre cómo hacerlo. En esta publicación, tengo la intención de dar un paseo por “Dockerizando Django” y exponer un puerto ejecutando uwsgi, que se puede usar para la producción a diferencia del servidor de desarrollo de Django.

Explicaré la mayoría de los pasos, sin embargo, recomiendo leer docker’s tutorial on images. Asumo que tienes Docker instalado y corriendo.

Ok, iniciemos.

En la raíz de nuestro proyecto Django (misma carpeta que manage.py) tendremos alguna estructura :

  • carpeta de requisitos, que contiene los requisitos de Python que debe instalar pip.
  • require.apt, que contiene los requisitos del sistema.
  • my_project.ini, que se utiliza para mantener las configuraciones de uwsgi.

El primer paso es proporcionar un Dockerfile en la raíz del proyecto, que le dice a Docker cómo construir la imagen. Mi Dockerfile se ve así:

FROM ubuntu:14.04
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV PYTHONBUFFERED 1

ADD ./requirements /requirements
ADD ./install_os_dependencies.sh /install_os_dependencies.sh
ADD ./requirements.apt /requirements.apt
ADD ./my_project.ini /my_project.ini

RUN ./install_os_dependencies.sh install

RUN pip3 install -r "requirements/requirements.txt"

RUN groupadd -r django && useradd -r -g django django
ADD . /app
RUN chown -R django /app
RUN chgrp -R django /app
WORKDIR /app

EXPOSE 8000

CMD sudo -u django uwsgi my_project.ini --master

Esto construirá nuestra imagen usando como base dockerhub’s ubuntu. Puede cambiar esto cambiando la primera línea, siempre que obtenga los requisitos para su otra imagen:

FROM ubuntu:14.04

Necesitamos generar los entornos locales explícitamente para evitar algunos problemas con Python y Unicode. Eso puede no ser necesario con otras imágenes.

RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV PYTHONBUFFERED 1

A continuación, agregamos los archivos necesarios para construir nuestra imagen:

ADD ./requirements /requirements
ADD ./install_os_dependencies.sh /install_os_dependencies.sh
ADD ./requirements.apt /requirements.apt
ADD ./my_project.ini /my_project.ini

install_os_dependencies.sh es un script bash que instalará los requisitos del sistema, que se enumeran en require.apt. Se inicia con:

RUN ./install_os_dependencies.sh install

Puede encontrar este script en PyDanny’s cookiecutter repository.

LEER
Cómo probar sus Content Types con el módulo Devel en Drupal 8

Estoy usando Python3 para este proyecto, por lo que mis requisitos.apt deben reflejar que:

##basic build dependencies of various Django apps for Ubuntu 14.04
#build-essential metapackage install: make, gcc, g++, 
build-essential
#required to translate
gettext
python3-dev
python3-pip

##shared dependencies of:
##Pillow, pylibmc
zlib1g-dev

##Postgresql and psycopg2 dependencies
libpq-dev

##Pillow dependencies
libtiff4-dev
libjpeg8-dev
libfreetype6-dev
liblcms1-dev
libwebp-dev

##pylibmc
libmemcached-dev
libssl-dev

##django-extensions
graphviz-dev


##lxml
libxml2-dev
libxslt-dev

En este punto, nuestra imagen tiene las dependencias básicas del sistema, instalemos nuestras dependencias de Python:

RUN pip3 install -r "requirements/requirements.txt"

El archivo requirements.txt debe estar en un formato que pip pueda entender. Para este proyecto, instalaré solo Django y uwsgi, por lo que el archivo es muy corto:

django==1.8.4
uWSGI==2.0.11.1

Ahora que todos los requisitos están instalados, crearemos un nuevo usuario con permisos más bajos, que usaremos para ejecutar uwsgi:

RUN groupadd -r django && useradd -r -g django django
ADD . /app
RUN chown -R django /app
RUN chgrp -R django /app
WORKDIR /app

WORKDIR es la forma preferida de Docker para cambiar directorios (no algo así como RUN cd).

Ok, tenemos nuestra aplicación y todos sus requisitos instalados. Necesitamos exponer un puerto para hablar con el mundo (8000 en este caso):

EXPOSE 8000

En este punto, podríamos ejecutar el servidor de desarrollo de nuestro Django y exponerlo, pero eso no sería útil para la producción. Agregaré uwsgi para ejecutar mi aplicación Python.
El siguiente paso es definir las configuraciones para uwsgi en my_project.ini:

[uwsgi]
http = :8000
chdir = /app/
env = DJANGO_SETTINGS_MODULE=config.settings
wsgi-file = config/wsgi.py
processes = 4
threads = 2

Con la directiva http, le estamos diciendo que sirva http. Es posible que desee utilizar sockets tcp o sockets Unix, lo que requerirá un cambio en esa configuración. Por ahora, solo quiero acceder al servidor desde mi navegador local, por lo que http es suficiente.
chdir le dice a uwsgi dónde está la aplicación.
Establecemos una variable de entorno para seleccionar una de nuestras configuraciones. Si tiene configuraciones específicas de instancia, puede cambiarlas aquí (local, prueba, producción, etc.).

LEER
¿Qué es AMP y por qué debería usarlo?

La última línea en nuestro Dockerfile define qué comando se ejecutará cuando comencemos nuestra imagen

CMD sudo -u django uwsgi my_project.ini --master

Corremos uwsgi como el usuario que creamos.

Ok, hemos terminado de construir nuestro Dockerfile. Es hora de verificar si podemos construir nuestra imagen (no olvide el.):

docker build -t django_app .

Si todo funciona, deberíamos tener algo como esto:

Successfully built dd40ad889782

Ese es el id the nuestra nueva imagen. Podemos correrla ahora:

docker run -p 8000:8000 -ti dd40ad889782

Le decimos a Docker qué puertos queremos reenviar (host: guest) con -p. -ti nos permite detener el contenedor con ctrl + C. Si no nos importa esto, esa bandera puede omitirse.

Suponiendo que su aplicación Django no tenga problemas, debería poder usarla desde https://localhost:8000.

Ni siquiera mencioné las bases de datos porque eso está más relacionado con la configuración de Django que con la configuración de Docker. Puede usar sqlite para que funcione.

Si desea inspeccionar las partes internas de su nuevo contenedor, puede acceder a ellas con:

docker exec -it weird_name bash

Donde weird_name es el nombre asignado por Docker a su contenedor. Si desea verificar sus contenedores en ejecución, puede ejecutar:

docker p

Esto debería ser suficiente para comenzar. Mantuve la mayoría de las cosas al mínimo para evitar una complejidad innecesaria.


Comentarios