Add a lot about Heroku
continuous-integration/drone/push Build is passing Details

But the deployment steps still need clarification.
For now, we just have a new app with database and backups.

Refs: #10
This commit is contained in:
Fred 2020-12-21 21:26:01 +01:00
parent 1027f5fc44
commit 30512fce2e
11 changed files with 236 additions and 80 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -367,7 +367,11 @@ urlpatterns = [
<2> Champomy et cotillons! Nous avons une correspondance avec `wishes/details/91827`
Nous n'allons pas nous occuper de l'accès à la base de données pour le moment (nous nous en occuperons dans un prochain chapitre) et nous nous contenterons de remplir un canevas avec un ensemble de données.
TODO: En fait, il faudrait quand même s'occuper du modèle ici.
TODO: et de la mise en place de l'administration, parce que nous en aurons besoin pour les étapes de déploiement.
[line-through]#Nous n'allons pas nous occuper de l'accès à la base de données pour le moment (nous nous en occuperons dans un prochain chapitre) et nous nous contenterons de remplir un canevas avec un ensemble de données.#
Le module `gwift.views` qui se trouve dans le fichier `gwift/views.py` peut ressembler à ceci:
[source,python]
@ -474,11 +478,30 @@ Nous avons donc la strucutre finale pour notre environnement de travail:
└── tox.ini
----
===
=== Cookie cutter
* Créez systématiquement un environnement virtuel pour chaque projet sur lequel vous travaillez
* La description des dépendances utilisées pour un projet doivent faire partie intégrante des sources
Pfiou! Ca en fait des commandes et du boulot pour "juste" démarrer un nouveau projet, non? Sachant qu'en plus, nous avons dû modifier des fichiers, déplacer des dossiers, ajouter des dépendances, configurer une base de données, ...
C'est ici que le projet http://cookiecutter.readthedocs.io/en/latest/readme.html[CookieCutter] va être intéressant: les X premières étapes peuvent être *bypassées* par une simple commande.
Bonne nouvelle! Il existe des générateurs, permettant de démarrer rapidement un nouveau projet sans (trop) se prendre la tête. Le plus connu (et le plus personnalisable) est https://cookiecutter.readthedocs.io/[Cookie-Cutter], qui se base sur des canevas _type https://pypi.org/project/Jinja2/[Jinja2]_, pour créer une arborescence de dossiers et fichiers conformes à votre manière de travailler. Et si vous avez la flemme de créer votre propre canevas, vous pouvez utiliser https://cookiecutter-django.readthedocs.io[ceux qui existent déjà].
Pour démarrer, créez un environnement virtuel (comme d'habitude):
[source,bash]
----
λ python -m venv .venvs\cookie-cutter-khana
λ .venvs\cookie-cutter-khana\Scripts\activate.bat
(cookie-cutter-khana) λ pip install cookiecutter
Collecting cookiecutter
[...]
Successfully installed Jinja2-2.11.2 MarkupSafe-1.1.1 arrow-0.17.0 binaryornot-0.4.4 certifi-2020.12.5 chardet-4.0.0 click-7.1.2 cookiecutter-1.7.2 idna-2.10 jinja2-time-0.2.0 poyo-0.5.0 python-dateutil-2.8.1 python-slugify-4.0.1 requests-2.25.1 six-1.15.0 text-unidecode-1.3 urllib3-1.26.2
(cookie-cutter-khana) λ cookiecutter https://github.com/pydanny/cookiecutter-django
[...]
[SUCCESS]: Project initialized, keep up the good work!
----
Si vous explorez les différents fichiers, vous trouverez beaucoup de similitudes avec la configuration que nous vous proposions ci-dessus.
En fonction de votre expérience, vous serez tenté de modifier certains paramètres, pour faire correspondre ces sources avec votre utilisation ou vos habitudes.

View File

@ -288,7 +288,8 @@ Found 4 errors in 1 file (checked 1 source file)
Pour corriger ceci, nous devons:
. Importer le type `Optional` et l'utiliser en sortie de notre fonction `first_int_elem`
. Eviter de lui donner de mauvais paramètres ;-)
. Eviter de lui donner de
mauvais paramètres ;-)
[source,python]
----
@ -458,9 +459,13 @@ Pour la petite histoire, `make` peu sembler un peu désuet, mais reste extrêmem
==== The Zen of Python
[source,text]
[source,python]
----
>>> import this
----
[source,text]
----
The Zen of Python, by Tim Peters
Beautiful is better than ugly.

View File

@ -85,8 +85,6 @@ include::heroku.adoc[]
include::docker.adoc[]
WARNING: le serveur de déploiement ne doit avoir qu'un accès en lecture au dépôt source.
On peut aussi passer par fabric, ansible, chef ou puppet.
@ -115,4 +113,3 @@ See https://mattsegal.dev/nginx-django-reverse-proxy-config.html
* Let's Encrypt !
include::database.adoc[]

View File

@ -1 +0,0 @@
=== Ansible

View File

@ -1,63 +0,0 @@
== Bases de données
On l'a déjà vu, Django se base sur un pattern type https://www.martinfowler.com/eaaCatalog/activeRecord.html[ActiveRecords] pour la gestion de la persistance des données et supporte les principaux moteurs de bases de données connus:
* SQLite (en natif, mais Django 3.0 exige une version du moteur supérieure ou égale à la 3.8)
* MariaDB (en natif depuis Django 3.0),
* PostgreSQL au travers de psycopg2 (en natif aussi),
* Microsoft SQLServer grâce aux drivers [...à compléter]
* Oracle via https://oracle.github.io/python-cx_Oracle/[cx_Oracle].
CAUTION: Chaque pilote doit être utilisé précautionneusement ! Chaque version de Django n'est pas toujours compatible avec chacune des versions des pilotes, et chaque moteur de base de données nécessite parfois une version spécifique du pilote. Par ce fait, vous serez parfois bloqué sur une version de Django, simplement parce que votre serveur de base de données se trouvera dans une version spécifique (eg. Django 2.3 à cause d'un Oracle 12.1).
Ci-dessous, quelques procédures d'installation pour mettre un serveur à disposition. Les deux plus simples seront MariaDB et PostgreSQL, qu'on couvrira ci-dessous. Oracle et Microsoft SQLServer se trouveront en annexes.
=== PostgreSQL
On commence par installer PostgreSQL.
Par exemple, dans le cas de debian, on exécute la commande suivante:
[source,bash]
----
$$$ aptitude install postgresql postgresql-contrib
----
Ensuite, on crée un utilisateur pour la DB:
[source,bash]
----
$$$ su - postgres
postgres@gwift:~$ createuser --interactive -P
Enter name of role to add: gwift_user
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
postgres@gwift:~$
----
Finalement, on peut créer la DB:
[source,bash]
----
postgres@gwift:~$ createdb --owner gwift_user gwift
postgres@gwift:~$ exit
logout
$$$
----
NOTE: penser à inclure un bidule pour les backups.
=== MariaDB
Idem, installation, configuration, backup, tout ça.
A copier de grimboite, je suis sûr d'avoir des notes là-dessus.
=== Microsoft SQL Server
=== Oracle

View File

@ -42,6 +42,71 @@ sudo make altinstall <1>
----
<1> *Attention !* Le paramètre `altinstall` est primordial. Sans lui, vous écraserez l'interpréteur initialement supporté par la distribution, et cela pourrait avoir des effets de bord non souhaités.
==== Installation de la base de données
On l'a déjà vu, Django se base sur un pattern type https://www.martinfowler.com/eaaCatalog/activeRecord.html[ActiveRecords] pour la gestion de la persistance des données et supporte les principaux moteurs de bases de données connus:
* SQLite (en natif, mais Django 3.0 exige une version du moteur supérieure ou égale à la 3.8)
* MariaDB (en natif depuis Django 3.0),
* PostgreSQL au travers de psycopg2 (en natif aussi),
* Microsoft SQLServer grâce aux drivers [...à compléter]
* Oracle via https://oracle.github.io/python-cx_Oracle/[cx_Oracle].
CAUTION: Chaque pilote doit être utilisé précautionneusement ! Chaque version de Django n'est pas toujours compatible avec chacune des versions des pilotes, et chaque moteur de base de données nécessite parfois une version spécifique du pilote. Par ce fait, vous serez parfois bloqué sur une version de Django, simplement parce que votre serveur de base de données se trouvera dans une version spécifique (eg. Django 2.3 à cause d'un Oracle 12.1).
Ci-dessous, quelques procédures d'installation pour mettre un serveur à disposition. Les deux plus simples seront MariaDB et PostgreSQL, qu'on couvrira ci-dessous. Oracle et Microsoft SQLServer se trouveront en annexes.
===== PostgreSQL
On commence par installer PostgreSQL.
Par exemple, dans le cas de debian, on exécute la commande suivante:
[source,bash]
----
$$$ aptitude install postgresql postgresql-contrib
----
Ensuite, on crée un utilisateur pour la DB:
[source,bash]
----
$$$ su - postgres
postgres@gwift:~$ createuser --interactive -P
Enter name of role to add: gwift_user
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
postgres@gwift:~$
----
Finalement, on peut créer la DB:
[source,bash]
----
postgres@gwift:~$ createdb --owner gwift_user gwift
postgres@gwift:~$ exit
logout
$$$
----
NOTE: penser à inclure un bidule pour les backups.
===== MariaDB
Idem, installation, configuration, backup, tout ça.
A copier de grimboite, je suis sûr d'avoir des notes là-dessus.
===== Microsoft SQL Server
===== Oracle
==== Préparation de l'environnement utilisateur
[source,bash]
@ -278,7 +343,7 @@ server {
<2> Ce répertoire sera complété par la commande `collectstatic` que l'on verra plus tard. L'objectif est que les fichiers ne demandant aucune intelligence soit directement servis par Nginx. Cela évite d'avoir un processus Python (relativement lent) qui doive être instancié pour servir un simple fichier statique.
<3> Afin d'éviter que Django ne reçoive uniquement des requêtes provenant de 127.0.0.1
=== Mise à jour
==== Mise à jour
Script de mise à jour.
@ -295,7 +360,7 @@ python manage.py collectstatic
gunicorn reload -HUP
----
=== Configuration des sauvegardes
==== Configuration des sauvegardes
Les sauvegardes ont été configurées avec borg: `yum install borgbackup`.
@ -315,7 +380,7 @@ Et dans le fichier crontab :
----
=== Rotation des jounaux
==== Rotation des jounaux
[source,bash]
----
@ -328,4 +393,6 @@ Et dans le fichier crontab :
}
----
Puis on démarre logrotate avec # logrotate -d /etc/logrotate.d/gwift pour vérifier que cela fonctionne correctement.
Puis on démarre logrotate avec # logrotate -d /etc/logrotate.d/gwift pour vérifier que cela fonctionne correctement.
==== Ansible

View File

@ -17,4 +17,6 @@ image.png
L'image de base python passe de 179 à 740 MB. Et là j'en ai pour presque 1,5 GB d'un coup.
Mais par contre, j'ai un python 3.7 direct et postgres 10 sans rien faire ou presque.
Mais par contre, j'ai un python 3.7 direct et postgres 10 sans rien faire ou presque.
La partie ci-dessous a été reprise telle quelle de https://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html[la documentation de cookie-cutter-django].

View File

@ -1 +1,127 @@
=== Heroku
https://www.heroku.com[Heroku] est une _Plateform As A Service_ footnote:[Aussi abrégé "PaaS" pour les conaisseurs], où vous choisissez le _service_ dont vous avez besoin (une base de données, un service de cache, un service applicatif, ...), vous lui envoyer les paramètres nécessaires et le tout démarre gentiment sans que vous ne deviez superviser l'hôte.
Ce mode démarrage ressemble énormément aux 12 facteurs dont nous avons déjà parlé plus tôt - raison de plus pour que notre application soit directement prête à y être déployée, d'autant plus qu'il ne sera pas possible de modifier un fichier une fois qu'elle aura démarré: si vous souhaitez modifier un paramètre, cela reviendra à couper l'actuelle et envoyer de nouveaux paramètres et recommencer le déploiement depuis le début.
.Invest in apps, not ops. Heroku handles the hard stuff — patching and upgrading, 24/7 ops and security, build systems, failovers, and more — so your developers can stay focused on building great apps.
image::images/deployment/heroku.png[]
Pour un projet de type "hobby" et pour l'exemple de déploiement ci-dessous, il est tout à fait possible de s'en sortir sans dépenser un kopek, afin de tester nos quelques idées ou mettre rapidement un _Most Valuable Product_ en place. La seule contrainte consistera à pouvoir héberger des fichiers envoyés par vos utilisateurs - ceci pourra être fait en configurant un _bucket S3_ chez Amazon (beurk), Scaleway ou OVH footnote:[Entre autres.]
Le fonctionnement est relativement simple: pour chaque application, Heroku crée un dépôt Git qui lui est associé. Au travers de la commande `heroku create`, vous associez en fait une nouvelle référence à votre code source:
[source,bash]
----
$ heroku create
Creating app... done, ⬢ young-temple-86098
https://young-temple-86098.herokuapp.com/ | https://git.heroku.com/young-temple-86098.git
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "heroku"]
url = https://git.heroku.com/still-thicket-66406.git
fetch = +refs/heads/*:refs/remotes/heroku/*
----
Pour envoyer une nouvelle version, il suffit dès lors (après l'avoir paramétrée), de pousser la référence grâce à la commande `git push heroku master`.
Prêt à vous lancer ? Commencez par créer un compte: https://signup.heroku.com/python.
==== Configuration du compte Heroku
+ Récupération des valeurs d'environnement pour les réutiliser ci-dessous.
Vous aurez peut-être besoin d'un coup de pouce pour démarrer votre première application; heureusement, la documentation est super bien faite:
.Heroku: Commencer à travailler avec un langage
image::images/deployment/heroku-new-app.png[]
Installez ensuite la CLI (_Command Line Interface_) en suivant https://devcenter.heroku.com/articles/heroku-cli[la documentation suivante].
Au besoin, cette CLI existe pour:
. macOS, _via_ `brew `
. Windows, grâce à un https://cli-assets.heroku.com/heroku-x64.exe[binaire x64] (la version 32 bits existe aussi, mais il est peu probable que vous en ayez besoin)
. GNU/Linux, via un script Shell `curl https://cli-assets.heroku.com/install.sh | sh` ou sur https://snapcraft.io/heroku[SnapCraft].
Une fois installée, connectez-vous:
[source,bash]
----
$ heroku login
----
Et créer votre application:
[source,bash]
----
$ heroku create
Creating app... done, ⬢ young-temple-86098
https://young-temple-86098.herokuapp.com/ | https://git.heroku.com/young-temple-86098.git
----
.Notre application est à présent configurée!
image::images/deployment/heroku-new-app-created.png[]
Ajoutons lui une base de données, que nous sauvegarderons à intervalle régulier:
[source,bash]
----
$ heroku addons:create heroku-postgresql:hobby-dev
Creating heroku-postgresql:hobby-dev on ⬢ still-thicket-66406... free
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pg:copy
Created postgresql-clear-39693 as DATABASE_URL
Use heroku addons:docs heroku-postgresql to view documentation
$ heroku pg:backups schedule --at '14:00 Europe/Brussels' DATABASE_URL
Scheduling automatic daily backups of postgresql-clear-39693 at 14:00 Europe/Brussels... done
----
[source,bash]
----
# Copié/collé de https://cookiecutter-django.readthedocs.io/en/latest/deployment-on-heroku.html
heroku create --buildpack https://github.com/heroku/heroku-buildpack-python
heroku addons:create heroku-redis:hobby-dev
heroku addons:create mailgun:starter
heroku config:set PYTHONHASHSEED=random
heroku config:set WEB_CONCURRENCY=4
heroku config:set DJANGO_DEBUG=False
heroku config:set DJANGO_SETTINGS_MODULE=config.settings.production
heroku config:set DJANGO_SECRET_KEY="$(openssl rand -base64 64)"
# Generating a 32 character-long random string without any of the visually similar characters "IOl01":
heroku config:set DJANGO_ADMIN_URL="$(openssl rand -base64 4096 | tr -dc 'A-HJ-NP-Za-km-z2-9' | head -c 32)/"
# Set this to your Heroku app url, e.g. 'bionic-beaver-28392.herokuapp.com'
heroku config:set DJANGO_ALLOWED_HOSTS=
# Assign with AWS_ACCESS_KEY_ID
heroku config:set DJANGO_AWS_ACCESS_KEY_ID=
# Assign with AWS_SECRET_ACCESS_KEY
heroku config:set DJANGO_AWS_SECRET_ACCESS_KEY=
# Assign with AWS_STORAGE_BUCKET_NAME
heroku config:set DJANGO_AWS_STORAGE_BUCKET_NAME=
git push heroku master
heroku run python manage.py createsuperuser
heroku run python manage.py check --deploy
heroku open
----