Despliegue de aplicación flask en un contenedor docker
Vamos a desplegar nuestra aplicación web desarrollada con flask en docker. Vamos a utilizar dos contenedores: uno para la base de datos mysql y otro para nuestra aplicación.
Seguimos las instrucciones de la documentación de docker para realizar la instalación en Ubuntu 16.04.
Contenedor de base de datos
Vamos a arrancar un contenedor que nos sirva la base de datos, indicamos la contraseña del usuario root y creamos una base de datos:
sudo docker run --name servidor_mysql -e MYSQL_DATABASE=tienda -e MYSQL_ROOT_PASSWORD=asdasd -d mysql
En al configuración de la conexión a la base de datos de nuestra aplicación, en el fichero config.py
tendremos que indicar los parámetros de conexión y la contraseña del root de mysql que vamos a mandar cunado creemos el contenedor, de la siguiente manera:
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:{}@{}/tienda'.format(os.environ["MYSQL_PASSWORD"],os.environ["MYSQL_PORT_3306_TCP_ADDR"])
Creando la imagen para el contenedor de nuestra aplicación
Clonamos la rama docker
del repositorio github donde tenemos los ficheros de nuestra aplicación:
$ git clone https://github.com/josedom24/tienda_videojuegos.git -b docker
En el repositorio tenemos un fichero Dockerfile
donde definimos las instrucciones que vamos a ejecutar para crear la imagen docker:
FROM ubuntu:16.04
MAINTAINER José Domingo Muñoz
RUN apt-get update -y && apt-get install -y \
apache2 \
libapache2-mod-wsgi-py3 \
python3-pip \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
ADD /tienda_videojuegos /var/www/html/tienda_videojuegos
RUN chown www-data:www-data -R /var/www/html/tienda_videojuegos
RUN pip3 install -r /var/www/html/tienda_videojuegos/requirements.txt
ADD 000-default.conf /etc/apache2/sites-available/
ADD app.wsgi /var/www/html/tienda_videojuegos
RUN service apache2 restart
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
EXPOSE 80
WORKDIR /var/www/html/tienda_videojuegos
COPY ./run.sh /
ENTRYPOINT ["/run.sh"]
También tenemos el fichero donde creamos la aplicación WSGI, app.wsgi
:
import sys
sys.path.insert(0, '/var/www/html/tienda_videojuegos')
from aplicacion.app import app as application
El fichero de configuración del virtualhost de apache2: 000-default.conf
:
...
DocumentRoot /var/www/html/tienda_videojuegos/aplicacion
WSGIDaemonProcess tienda user=www-data group=www-data threads=5
WSGIScriptAlias / /var/www/html/tienda_videojuegos/app.wsgi
<Directory /var/www/html/tienda_videojuegos/aplicacion>
WSGIProcessGroup tienda
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
...
Y por último el fichero run.sh
que el script que se va a ejecutar cuando creemos el contenedor:
#!/bin/bash
python3 manage.py create_tables
python3 manage.py add_data_tables
/usr/sbin/apache2ctl -D FOREGROUND
Creamos las tablas con los datos de ejemplo de la base de datos y ejecutamos el servidor apache2.
Para crear la imagen ejecutamos el siguiente comando:
$ cd tienda_videojuegos
$ sudo docker build -t tienda .
Y comprobamos que hemos generado la nueva imagen:
$ sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
tienda latest bb1d87c90448 46 hours ago 474MB
ubuntu 16.04 ccc7a11d65b1 11 days ago 120MB
mysql latest c73c7527c03a 3 weeks ago 412MB
Contenedor con nuestra aplicación
Para crear el contenedor con nuestra aplicación:
$ sudo docker run --name mytienda -e MYSQL_PASSWORD=asdasd -p 8080:80 --link servidor_mysql:mysql -d tienda
Comprobamos que los contenedores se están ejecutando:
$ sudo docker ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
08eadf7d87b0 tienda "/run.sh" 4 seconds ago Up 3 seconds 0.0.0.0:8080->80/tcp mytienda
6ccff57702ba mysql "docker-entrypoint..." 16 seconds ago Up 16 seconds 3306/tcp servidor_mysql
Si queremos crear el usuario administrador de nuestra aplicación podemos acceder de forma interactiva a nuestro contenedor para ejecutar la instrucción necesaria:
$ sudo docker exec -i -t mytienda /bin/bash
root@5db96abf79b3:/var/www/html/tienda_videojuegos# python3 manage.py create_admin
Por ultimo comprobamos que la aplicación está funcionando accediendo a la ip del servidor y al puerto 8080: