Despliegue de aplicaciones python
Procedimiento
Entorno de desarrollo
Lo primero será crear el entorno virtual y activarlo:
mkdir venv
cd venv
python3 -m venv django
source django/bin/activate
Además, instalaremos la aplicación de Django:
pip install django
Después de realizar un fork del repositorio de la aplicación, clonaremos el repositorio en la máquina local usando el comando git clone
con el repositorio.
Para usar esta aplicación se va a trabajar usando una base de datos SQLite, por lo que no es necesario instalar ningún servicio de base de datos. Para consultar el nombre de la base de datos, se puede ver el fichero /django_tutorial/settings.py
y vemos que su nombre es db.sqlite3
:
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
A continuación, se va a crear una base de datos vacía para la aplicación y un superusuario para poder acceder a la aplicación:
python manage.py migrate
python manage.py createsuperuser
Además, es necesario editar el fichero django_tutorial/settings.py
y modificar la variable ALLOWED_HOSTS
para que pueda acceder sin problemas a la aplicación desde cualquier host:
ALLOWED_HOSTS = ['*']
Para poder acceder, como estamos usando bravo
, debemos añadir una nueva regla DNAT para que se redirija el tráfico de la máquina bravo
al puerto 8000
de la máquina alfa
editando el fichero /etc/network/interfaces.d/50-cloud-init
:
post-up iptables -t nat -A PREROUTING -p tcp --dport 8000 -i ens3 -j DNAT --to 172.16.0.200
Y reiniciamos la maquina para que se apliquen los cambios.
Lo siguiente es ejecutar el servidor web de desarrollo para comprobar los datos que se han modificado entrando en la zona de administración de la aplicación (/admin
):
python manage.py runserver 0.0.0.0:8000
Aparecerá una pantalla como la siguiente:
Si entramos en la zona de administración de la aplicación (/admin
), aparecerá una pantalla como la siguiente:
Lo siguiente será entrar como administrador y crear un par de cuestiones. El usuario y contraseña que pide la página /admin
es el que se ha creado con el comando python manage.py createsuperuser
:
Una vez creadas las preguntas, podemos comprobar que se han creado correctamente entrando en /polls
:
Si entramos en la zona de administración de la aplicación (/admin
), y seleccionamos una de las dos preguntas que hemos creado, aparecerá una pantalla como la siguiente mostrando los detalles de la pregunta y las votaciones que ha recibido:
- Configura el servidor web apache2 con el módulo wsgi para servir la página web. Si utilizas como entorno de desarrollo la máquina bravo, se accederá con el nombre python.tunombre.gonzalonazareno.org.
A continuación, vamos a configurar el servidor web Apache para que pueda servir la aplicación Django usando wsgi. Para ello, debemos instalar el módulo para wsgi:
sudo dnf install python3-mod_wsgi
*Nota: Para hacer este apartado se han usado los talleres: Desplegando aplicaciones flask con apache2 + mod_wsgi y Desplegando aplicaciones flask con apache2/nginx + uwsgi
Movemos el directorio django_tutorial
y el entorno virtual a la carpeta /var/www/html
para que sea accesible desde el servidor web:
mv github/django_tutorial /var/www/html
mv venv/django /var/www/html
Lo siguiente será editar el fichero django_tutorial/settings.py
y modificar la variable ALLOWED_HOSTS
para que pueda acceder sin problemas a la aplicación desde cualquier host y añadimos STATIC_ROOT
para que se pueda acceder a los ficheros estáticos:
ALLOWED_HOSTS = ['*']
STATIC_ROOT = '/var/www/html/django_tutorial/static/'
Dentro de django_tutorial
creamos el contenido estático de la aplicación:
sudo python3 manage.py collectstatic
Creamos un fichero de configuración para el servidor apache, /etc/httpd/sites-available/django_apache.conf
:
<VirtualHost *:80>
ServerName python.nazareth.gonzalonazareno.org
DocumentRoot /var/www/html/django_tutorial
Alias /static/ /var/www/html/django_tutorial/static/
WSGIDaemonProcess django_tutorial python-path=/var/www/html/django_tutorial:/var/www/html/django/lib/python3.9/site-packages
WSGIProcessGroup django_tutorial
WSGIScriptAlias / /var/www/html/django_tutorial/django_tutorial/wsgi.py
ErrorLog /var/log/httpd/django_tutorial_error.log
CustomLog /var/log/httpd/django_tutorial_access.log combined
</VirtualHost>
Y lo activamos:
sudo ln -s /etc/httpd/sites-available/django_apache.conf /etc/httpd/sites-enabled/
sudo systemctl restart httpd
Ya podemos entrar en la aplicación desde el navegador introduciendo la dirección:
python.nazareth.gonzalonazareno.org
Entorno de producción
Vamos a realizar el despliegue de nuestra aplicación en un entorno de producción, para ello vamos a utilizar nuestro VPS.
Lo primero será clonar el repositorio de la aplicación en el VPS:
git clone https://github.com/belennazareth/django_tutorial.git
Instalamos python3 y pip3:
apt-get install python3-venv
apt-get install python3-pip
Creamos un entorno virtual para la aplicación y lo activamos:
python3 -m venv venv/django
source venv/django/bin/activate
Instalamos las dependencias de la aplicación:
pip install -r django_tutorial/requirements.txt
Necesitamos poder trabajar con mysql desde python, para ello instalamos el conector:
sudo apt install libmariadb-dev
pip install mysqlclient
pip install pymysql
Creamos la base de datos y el usuario para la aplicación, es importante que el usuario y la contraseña sean los mismos que en sqlite:
sudo mysql
CREATE DATABASE django;
CREATE USER 'django'@'localhost' IDENTIFIED BY 'django';
GRANT ALL PRIVILEGES ON django.* TO 'django'@'localhost';
FLUSH PRIVILEGES;
Modificamos el fichero django_tutorial/settings.py
para que la aplicación pueda conectarse a la base de datos:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django',
'USER': 'django',
'PASSWORD': 'django',
'HOST': 'localhost',
'PORT': '',
}
}
En bravo, creamos una copia de seguridad de la aplicación:
sudo python3 manage.py dumpdata > db.json
Subimos la copia al repositorio:
git add db.json
git commit -m "Copia de seguridad"
git push
En la máquina del VPS, actualizamos el repositorio:
git pull
Y restauramos la copia de seguridad en el VPS:
python3 manage.py migrate
python3 manage.py loaddata db.json
Editamos el fichero django_tutorial/settings.py
para que la aplicación pueda servir los ficheros estáticos:
ALLOWED_HOSTS = ['*']
STATIC_ROOT = '/home/poke/django_tutorial/static/'
Y generamos el contenido estático:
python3 manage.py collectstatic
Configuraremos nginx instalando primero el paquete nginx
y uwsgi
:
sudo apt install nginx
pip install uwsgi
Creamos dentro de la carpeta del entorno virtual el fichero de configuración de nginx, /home/poke/venv/django/servidor.ini
:
[uwsgi]
http = :8080
chdir = /home/poke/django_tutorial
wsgi-file = django_tutorial/wsgi.py
processes = 4
threads = 2
Como vimos en el taller, creamos una unidad systemd para que el servicio se inicie automáticamente editando el fichero /etc/systemd/system/uwsgi-django.service
:
[Unit]
Description=uwsgi-django
After=network.target
[Install]
WantedBy=multi-user.target
[Service]
User=www-data
Group=www-data
Restart=always
ExecStart=/home/poke/venv/django/bin/uwsgi /home/poke/venv/django/servidor.ini
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
WorkingDirectory=/home/poke/django_tutorial
Environment=PYTHONPATH='/home/poke/django_tutorial:/home/poke/venv/django/lib/python3.9/site-packages'
PrivateTmp=true
Y lo activamos:
sudo systemctl enable uwsgi-django
sudo systemctl start uwsgi-django
Por último, creamos el fichero de configuración de nginx, /etc/nginx/sites-available/django.conf
copiando el existente con https y cambiando la línea location /
y servername por python.ottershell.es
:
server {
listen 80;
listen 443 ssl http2;
server_name pyhton.ottershell.es;
access_log /var/log/nginx/python.com-access.log;
error_log /var/log/nginx/python.com-error.log;
ssl_certificate /etc/letsencrypt/live/ottershell.es/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ottershell.es/privkey.pem;
root /home/poke/django_tutorial;
index index.php;
location / {
proxy_pass http://localhost:8080;
include proxy_params;
}
location /static/polls {
alias /home/poke/django_tutorial/polls/static/polls;
}
location /static/admin {
alias /home/poke/venv/django/lib/python3.9/site-packages/django/contrib/admin/static/admin/;
}
}
Desactivamos el DEBUG en el fichero django_tutorial/settings.py
para que no se muestren los errores y den información sensible:
DEBUG = False
Creamos el enlace simbólico y reiniciamos el servicio:
sudo ln -s /etc/nginx/sites-available/django /etc/nginx/sites-enabled/
sudo systemctl restart nginx
En la página donde tenemos contratado el dominio, añadimos un nuevo registro de tipo CNAME
con el nombre python
y el valor ottershell.es
.
Si entramos en python.ottershell.es, veremos nuestra aplicación funcionando:
Modificación de nuestra aplicación
Las modificaciones se realizarán en el entorno de desarrollo, en mi caso bravo
. Una vez realizadas, se subirán al repositorio y se actualizará el entorno de producción.
Desarrollo
Modificamos la página inicial donde se ven las encuestas para que aparezca tu nombre editando el archivo django_tutorial/polls/templates/index.html
:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Django Tutorial</title>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Almarai:wght@800&family=Nunito+Sans&display=swap" />
</head>
<body>
<div class="container">
<div class="content">
<img src="https://dit.gonzalonazareno.org/gestiona/static/img/iesgn.jpg" alt="DigitalOcean Logo" width="100" />
<h1>Aplicación <a href="https://www.djangoproject.com/">Django Tutorial</a>!<br>Belen Nazareth Duran Melendez</h1>
Modificamos la imagen que se ve de fondo en la página de inicio añadiendo una nueva imagen en django_tutorial/polls/static/polls/images
y editando el archivo django_tutorial/polls/static/polls/style.css
:
li a {
color: black;
background-color: blanchedalmond;
}
body {
background: white url("images/background3.jpg");
}
Vamos a crear una nueva tabla en la base de datos siguiendo estos pasos:
- Creamos un nuevo modelo en
django_tutorial/polls/models.py
:
class Categoria(models.Model):
Abr = models.CharField(max_length=4)
Nombre = models.CharField(max_length=50)
def __str__(self):
return self.Abr+" - "+self.Nombre
- Creamos las migraciones:
sudo python3 manage.py makemigrations --name nueva_categoria
sudo python3 manage.py migrate
- Obtenemos una salida parecida a esta:
(django) [nazare@bravo django_tutorial]$ sudo python3 manage.py makemigrations --name nueva_categoria
Migrations for 'polls':
polls/migrations/0002_nueva_categoria.py
- Create model Categoria
(django) [nazare@bravo django_tutorial]$ sudo python3 manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Applying polls.0002_nueva_categoria... OK
- Añadimos el nuevo modelo a la interfaz de administración en
django_tutorial/polls/admin.py
cambiando la líneafrom .models import Question
por:
from .models import Choice, Question, Categoria
- Al final del fichero, añadimos:
admin.site.register(Categoria)
- Para poder trasladar los cambios:
sudo python3 manage.py
sudo python3 manage.py dumpdata > db2.json
sudo python3 manage.py collectstatic
git add *
git commit -m "Añadida nueva tabla + cambios en la página de inicio"
git push
Producción
Realizamos los cambios en el entorno de producción:
git pull
python3.9 manage.py migrate
python3.9 manage.py loaddata db2.json
python3.9 manage.py collectstatic
Y vemos como se ha actualizado la página de inicio:
*Nota: Activar los entornos virtuales, en bravo ahora esta en /var/www/, no usar emojis en sqlite, las maquinas usadas son bravo y buizel con usuario poke
Repositorio Github: https://github.com/belennazareth/django_tutorial