Hi ha diverses eines per a poder realitzar aquest desplegament. Les opcions més habituals son:
mod_wsgi.
En aquest article ho farem amb Apache + mod_wsgi.
En un projecte amb Django i React, cal tenir clar que hi ha una part de processament al servidor (Django) que ha de respondre les peticions que requereixen accés i manipulació de les dades a la BD (bàsicament serà l'API i l'admin panel), i una part que s'executa al client (React) i que des del punt de vista del servidor son simples arxius estàtics.
A més d'això, per la part de servidor també caldrà servir els arxius estàtics de la part Django (al menys per l'admin panel) i les possibles càrregues (uploads) que es solen parlar com d'arxius media.
Per altra banda, cal fer servir un motor de BD adequat com Postgre, MySQL, MariaDB o Oracle. SQLite no és una opció per producció, tot i que va bé per desenvolupament i una part del testing.
En resum:
/api : React necessita interactuar amb l'app per aquesta via./admin : l'admin panel de Django que ens permet tenir un CRUD fàcil de tots els elements de la BD sense haver de realitzar gaire codi./static: arxius estàtics, bàsicament per a l'admin panel./media: arxius media (càrregues, uploads)./: arxius estàtics, únic arxiu a index.html/assets: resta d'arxius estàtics
Abans de començar necessitem disposar de:
Assumim que el servidor que disposem és dedicat únicament a aquesta app. És possible configurar diverses aplicacions en un server, però en ares de la simplicitat ho plategem així.
Configurem primer de tot la BD de producció. Farem servir MariaDB però es podrien seguir pràcticament les mateixes passes per MySQL. Per a PostgreSQL o Oracle canviara força coses de la creació de l'espai d'usuari i esquemes.
$ sudo apt update $ sudo apt install mariadb-server $ sudo mysql mysql> create user biblio@localhost identified by "biblio123"; mysql> grant all on biblio.* to biblio@localhost; mysql> create database biblio;
Mai poseu una password tan evident com «biblio123» en producció. Això està bé en development local, però no en cap servidor públic, per molt que els ports de la BD no siguin públics des de fora.
Amb això ja tindríem instal·lada la BD, amb un usuari biblio i amb accés a la DB biblio.
Instal·lem dependències del sistema. Utilitzarem Python venv per a la gestió de les biblioteques de codi.
Haurem d'afegir el paquet mysqlclient de Python que potser no es feia servir en desenvolupament.
Assumim que el projecte Django utilitza un plugin com django-environ o django-dotenv per a la gestió de les credencials. Si no ho tens, pots fer un cop d'ull a l'article django-environ i el vcs.
També assumim que instal·larem l'aplicació Django al home directory de l'usuari principal del sistema, com super o isard. També seria adequat fer-ho en una carpeta de sistema (p.ex. /var/www/) si es tractés d'un entorn multiusuari, situació menys freqüent actualment ja que es sol tenir un contenidor LXC o VM específic per a cada aplicació.
$ sudo apt install default-libmysqlclient-dev python3-dev python3-venv git $ git clone https://github.com/elmeuusuari/projecte-django-react $ cd projecte-django-react $ python3 -m venv env $ source env/bin/activate (env) $ pip install -r requirements.txt (env) $ pip install mysqlclient (env) $ cp .env.example .env
Ajusta els valors de .env, en particular activa la línia d'exemple per a MariaBD i comenta la de sqlite.
També ajusta el domini elmeudomini.com com pertoqui:
SECRET_KEY=sdjfhisdfg67sdtf78ewhf8w3efheh7uf9iehfj98er DATABASE_URL=mysql://biblio:biblio123@127.0.0.1:3306/biblio #DATABASE_URL=sqlite:///db.sqlite3 ALLOWED_HOSTS=elmeudomini.com CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173,https://elmeudomini.com
Fixeu-vos que ALLOWED_HOSTS hem tret el domini wildcard «*» i només deixem el domini real en producció. Son mesures de seguretat importants.
Ara ja podem acabar de fer comprovacions i crear les taules de la BD:
(env) $ ./manage.py check (env) $ ./manage.py migrate (env) $ ./manage.py createsuperuser
Podeu fer també un runserver i fer proves amb el servidor de desenvolupament si podeu accedir al port 8000 (sempre i quan tingueu aquest port obert externament):
(env) $ ./manage.py runserver
Amb el servidor de desenvolupament obert podeu provar d'accedir (amb una altra shell) a l'API o l'admin panel amb:
$ curl localhost:8000/api/llibres $ curl localhost:8000/admin
Assumim que disposem de la part de React del projecte a la carpeta /react, tot i que podria ser perfectament un repositori a part
Instal·lem NodeJS versió LTS. Primer instal·lem la versió que hi hagi als repos del sistema operatiu que tinguem, i després fem un upgrade amb l'eina n:
sudo apt install nodejs npm sudo npm i -g n sudo n lts
Tanqueu el terminal o la connexió SSH perquè els canvis de la versió de NodeJS prenguin efecte.
Aneu a la carpeta de React, configurem i compilem:
$ cd /ruta/a/la/carpeta/react $ npm install $ cp src/config.js.example src/config.js
Editeu src/config.js, bàsicament canviar les URLs d'accés amb l'esquema complert de https://elmeudomini.com .
Un cop configurat amb els dominis adequats, podem compilar l'app React.
$ npm run build
El npm run build crearà una carpeta dist/ on hi haurà els arxius estàtics per al desplegament, en particular el punt d'entrada únic index.html.
Probablement haureu clonat el repositori del projecte al home directory de l'usuari que tingueu, per exemeple super o isard. Aquesta carpeta del home directory com /home/super/ sol tenir permisos restringits per protegir les dades en sistemes multiusuari, però com que no és el nostre cas (assumim un entorn monousuari), podem obrir els permisos per facilitar que Apache pugui arribar i llegir les carpetes del projecte:
$ chmod 755 ~
Necessitem recollir tots els arxius estàtics del projecte Django per servir-los a la URL /static. La instrucció collectstatic ens ho facilitarà, però abans caldrà modificar settings.py per indicar el nom de la carpeta d'arxius estàtics. Localitzeu la línia amb:
STATIC_URL = 'static/'
I afegiu a darrera el nom de la carpeta o vulgueu els arxius estàtics (podeu triar el nom):
STATIC_ROOT = 'static/'
Ara ja podeu recollir tots els arxius estàtics de l'app Django i del seu admin panel:
(env) $ ./manage.py collectstatic
Ara sí! Instal·lem Apache i el mòdul mod_wsgi que ens permetrà connectar Apache a l'app Python. WSGI és un estàndard de comunicació entre servidors i aplicacions web (Web Server Gateway Interface), tot que es fa servir bàsicament en aquestes apps Python com Django, Flask o FastAPI.
$ sudo apt install apache2 libapache2-mod-wsgi-py3 $ sudo a2enmod rewrite
La configuració, com hem vist al principi, no és senzilla. Recopilem el què anem a fer:
/api : React necessita interactuar amb l'app per aquesta via./admin : l'admin panel de Django que ens permet tenir un CRUD fàcil de tots els elements de la BD sense haver de realitzar gaire codi./static: arxius estàtics, bàsicament per a l'admin panel./media: arxius media (càrregues, uploads)./: arxius estàtics, únic arxiu a index.html/assets: resta d'arxius estàtics
Assumim que tenim una configuració monousuari i monoaplicació (una VM o CT dedicat per a aquesta app). En aquest cas podeu implementar directament a la site per defecte d'Apache /etc/apache2/sites-available/000-default.conf:
<VirtualHost *:80> # Si només tenim 1 domini, no cal anomenar-lo #ServerName www.example.com WSGIDaemonProcess myapp python-home=/home/super/django-react/env python-path=/home/super/django-react WSGIProcessGroup myapp WSGIScriptAlias / /home/super/django-react/djangoreact/wsgi.py <Directory /home/super/django-react/djangoreact> <Files wsgi.py> Require all granted </Files> </Directory> Alias /static/ /home/super/django-react/static/ <Directory /home/super/django-react/static> Require all granted </Directory> Alias /media/ /home/super/django-react/media/ <Directory /home/super/django-react/media> Require all granted </Directory> # REACT FRONTEND Alias /assets /home/super/django-react/react/dist/assets/ Alias /index.html /home/super/django-react/react/dist/index.html AliasMatch ^/$ /home/super/django-react/react/dist/index.html <Directory /home/super/django-react/react/dist> Require all granted </Directory> # Regla de reescriptura per a React Router # Les rutes conegudes no entren: /admin /api /static /media i /assets # La resta de rutes van a dist/index.html (React Router) RewriteEngine On RewriteCond %{REQUEST_URI} !^/admin RewriteCond %{REQUEST_URI} !^/api RewriteCond %{REQUEST_URI} !^/static RewriteCond %{REQUEST_URI} !^/media RewriteCond %{REQUEST_URI} !^/assets RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ /home/super/django-react/react/dist/index.html [L] ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Reinicia Apache amb:
$ sudo systemctl restart apache2.service
Si no et dona errors al reiniciar Apache, prova les següents comprovacions.
Django funciona a /api i /admin:
$ curl https://elmeudomini.com/api/llibres $ curl https://elmeudomini.com/admin
Si no es veu des de fora amb el domini, intenta comprovar que sí que funciona des de dins:
$ curl http://localhost/api/llibres $ curl http://localhost/admin
En particular, comprova que els arxius estàtics es veuen quan anem a /admin.
Funciona el frontend de React a https://elmeudomini.com (amb el navegador).
Si no es veu des de fora, intenta la comprovació interna:
$ curl http://localhost
Si apareix la pàgina de React però no carrega les dades de l'API, obre la consola de Javascript del navegador i investiga el problema que estigui succeint (CORS, etc.)
Comproveu que es pot accedir a /admin i que podeu afegir llibres amb imatges.
Si us dona problemes, segurament és que necessitareu donar permisos a /media perquè Apache hi pugui escriure:
$ sudo chown -R www-data /home/super/django-react/media