Migrer votre projet Django vers Heroku
Dans ce didacticiel, nous prendrons un simple projet Django local, soutenu par une base de données MySQL, et le convertirons pour qu'il s'exécute sur Heroku. Amazon S3 sera utilisé pour héberger nos fichiers statiques, tandis que Fabric automatisera le processus de déploiement.
Le Projet est un système de messagerie simple. Il peut s'agir d'une application de tâches, d'un blog ou même d'un clone de Twitter. Pour simuler un scénario réel, le projet sera d'abord créé avec un backend MySQL, puis converti en Postgres pour être déployé sur Heroku. J'ai personnellement eu cinq ou six projets dans lesquels j'ai dû faire exactement cette chose : convertir un projet local, soutenu par MySQL, en une application live sur Heroku.
Installation
Conditions préalables
- Lisez le guide officiel de démarrage rapide de Django sur Heroku. Lisez-le simplement. Cela vous aidera à avoir une idée de ce que nous allons accomplir dans ce didacticiel. Nous utiliserons le didacticiel officiel comme guide pour notre propre processus de déploiement plus avancé.
- Créez un compte AWS et configurez un compartiment S3 actif.
- Installez MySQL.
Commençons
Commencez par télécharger le projet de test ici, décompressez-le, puis activez un virtualenv :
$ cd django_heroku_deploy
$ virtualenv --no-site-packages myenv
$ source myenv/bin/activate
Créez un nouveau dépôt sur Github :
$ curl -u 'USER' https://api.github.com/user/repos -d '{"name":"REPO"}'
Assurez-vous de remplacer les MOTS-CLÉS en majuscules par vos propres paramètres. Par exemple :
curl -u 'mjhea0' https://api.github.com/user/repos -d '{"name":"django-deploy-heroku-s3"}'
Ajoutez un fichier Lisez-moi, initialisez le dépôt Git local, puis PUSH la copie locale sur Github :
$ touch README.md
$ git init
$ git add .
$ git commit -am "initial"
$ git remote add origin https://github.com/username/Hello-World.git
$ git push origin master
Assurez-vous de remplacer l'URL par l'URL de votre dépôt que vous avez créée à l'étape précédente.
Configurez une nouvelle base de données MySQL appelée django_deploy :
$ mysql.server start
$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
mysql> CREATE DATABASE django_deploy;
Query OK, 1 row affected (0.01 sec)
mysql>
mysql> quit
Bye
Mettez à jour settings.py :
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_deploy',
'USER': 'root',
'PASSWORD': 'your_password',
}
}
Installez les dépendances :
$ pip install -r requirements.txt
$ python manage.py syncdb
$ python manage.py runserver
Exécutez le serveur à l'adresse http://localhost:8000/admin/ et assurez-vous que vous pouvez vous connecter à l'administrateur. Ajoutez quelques éléments à l'objet Whatever
. Tuez le serveur.
Convertir de MySQL vers Postgres
Remarque : Dans cette situation hypothétique, imaginons que vous travaillez sur ce projet depuis un certain temps en utilisant MySQL et que vous souhaitez maintenant le convertir en Postgres.
Installer les dépendances :
$ pip install psycopg2
$ pip install py-mysql2pgsql
Configurez une base de données Postgres :
$ psql -h localhost
psql (9.2.4)
Type "help" for help.
michaelherman=# CREATE DATABASE django_deploy;
CREATE DATABASE
michaelherman=# \q
Migrer les données :
$ py-mysql2pgsql
Cette commande crée un fichier appelé mysql2pgsql.yml, contenant les informations suivantes :
mysql:
hostname: localhost
port: 3306
socket: /tmp/mysql.sock
username: foo
password: bar
database: your_database_name
compress: false
destination:
postgres:
hostname: localhost
port: 5432
username: foo
password: bar
database: your_database_name
Mettez à jour ceci pour votre configuration. Cet exemple couvre simplement la conversion de base. Vous pouvez également inclure ou exclure certains tableaux. Voir l’exemple complet ici.
Transférez les données :
$ py-mysql2pgsql -v -f mysql2pgsql.yml
Une fois les données transférées, assurez-vous de mettre à jour votre fichier settings.py :
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "your_database_name",
"USER": "foo",
"PASSWORD": "bar",
"HOST": "localhost",
"PORT": "5432",
}
}
Enfin, resynchronisez la base de données, exécutez le serveur de test et ajoutez un autre élément à la base de données pour vous assurer que la conversion a réussi.
Ajouter un fichier local_settings.py
En ajoutant un fichier local_settings.py, vous pouvez étendre le fichier settings.py avec des paramètres pertinents pour votre environnement local, tandis que le fichier principal settings.py Le fichier est utilisé uniquement pour vos environnements de transfert et de production.
Assurez-vous d'ajouter local_settings.py à votre fichier .gitignore afin de garder le fichier hors de vos référentiels. Ceux qui souhaitent utiliser ou contribuer à votre projet peuvent ensuite cloner le dépôt et créer leur propre fichier local_settings.py spécifique à leur propre environnement local.
Bien que cette méthode d'utilisation de deux fichiers de paramètres soit une convention depuis plusieurs années, de nombreux développeurs Python utilisent désormais un autre modèle appelé The One True Way. Nous pourrions examiner ce modèle dans un prochain tutoriel.
Mettre à jour les paramètres.py
Nous devons apporter trois modifications à notre fichier settings.py actuel :
Changez le mode DEBUG
sur false :
DEBUG = False
Ajoutez le code suivant au bas du fichier :
# Allow all host hosts/domain names for this site
ALLOWED_HOSTS = ['*']
# Parse database configuration from $DATABASE_URL
import dj_database_url
DATABASES = { 'default' : dj_database_url.config()}
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# try to load local_settings.py if it exists
try:
from local_settings import *
except Exception as e:
pass
Mettez à jour les paramètres de la base de données :
# we only need the engine name, as heroku takes care of the rest
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
}
}
Créez votre fichier local_settings.py :
$ touch local_settings.py
$ pip install dj_database_url
Ajoutez ensuite le code suivant :
from settings import PROJECT_ROOT, SITE_ROOT
import os
DEBUG = True
TEMPLATE_DEBUG = True
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "django_deploy",
"USER": "foo",
"PASSWORD": "bar",
"HOST": "localhost",
"PORT": "5432",
}
}
Lancez le serveur de test pour vous assurer que tout fonctionne toujours. Ajoutez quelques enregistrements supplémentaires à la base de données.
Configuration Heroku
Ajoutez un Procfile au répertoire principal :
$ touch Procfile
et ajoutez le code suivant au fichier :
web: python manage.py runserver 0.0.0.0:$PORT --noreload
Installez la ceinture d'outils Heroku :
$ pip install django-toolbelt
Gelez les dépendances :
$ pip freeze > requirements.txt
Mettez à jour le fichier wsgi.py :
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
Testez vos paramètres Heroku localement :
$ foreman start
Accédez à http://localhost:5000/.
Vous avez l'air bien ? Faisons fonctionner Amazon S3.
Amazone S3
Bien qu'il soit hypothétiquement possible d'héberger des fichiers statiques dans votre dépôt Heroku, il est préférable d'utiliser un hébergeur tiers, surtout si vous disposez d'une application destinée aux clients. S3 est facile à utiliser et ne nécessite que quelques modifications de votre fichier settings.py.
Installer les dépendances :
$ pip install django-storages
$ pip install boto
Ajoutez des stockages
et boto
à vos INSTALLED_APPS
dans « settings.py »
Ajoutez le code suivant au bas de « settings.py » :
# Storage on S3 settings are stored as os.environs to keep settings.py clean
if not DEBUG:
AWS_STORAGE_BUCKET_NAME = os.environ['AWS_STORAGE_BUCKET_NAME']
AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
STATIC_URL = S3_URL
Les paramètres dépendants de l'environnement AWS sont stockés en tant que variables d'environnement. Nous n'avons donc pas besoin de les définir depuis le terminal à chaque fois que nous exécutons le serveur de développement, nous pouvons les définir dans notre script virtualenv activate
. Récupérez le nom du compartiment AWS, l'ID de clé d'accès et la clé d'accès secrète de S3. Ouvrez myenv/bin/activate
et ajoutez le code suivant (assurez-vous d'ajouter les informations spécifiques que vous venez d'extraire de S3) :
# S3 deployment info
export AWS_STORAGE_BUCKET_NAME=[YOUR AWS S3 BUCKET NAME]
export AWS_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
Désactivez et réactivez votre virtualenv, puis lancez le serveur local pour vous assurer que les modifications ont pris effet :
$ foreman start
Tuez le serveur, puis mettez à jour le fichier requirements.txt :
$ pip freeze > requirements.txt
Pousser vers Github et Heroku
Sauvegardeons nos fichiers sur Github avant de les PUSH vers Heroku :
$ git add .
$ git commit -m "update project for heroku and S3"
$ git push -u origin master
Créez un projet/dépôt Heroku :
$ heroku create <name>
Nommez-le comme vous le souhaitez.
POUSSER vers Heroku :
$ git push heroku master
Envoyer les variables d'environnement AWS à Heroku
$ heroku config:set AWS_STORAGE_BUCKET_NAME=[YOUR AWS S3 BUCKET NAME]
$ heroku config:set AWS_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
$ heroku config:set AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXX
Collectez les fichiers statiques et envoyez-les à Amazon :
$ heroku run python manage.py collectstatic
Ajouter une base de données de développement :
$ heroku addons:add heroku-postgresql:dev
Adding heroku-postgresql on deploy_django... done, v13 (free)
Attached as HEROKU_POSTGRESQL_COPPER_URL
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pgbackups:restore.
Use `heroku addons:docs heroku-postgresql` to view documentation.
$ heroku pg:promote HEROKU_POSTGRESQL_COPPER_URL
Promoting HEROKU_POSTGRESQL_COPPER_URL to DATABASE_URL... done
Synchronisez maintenant la base de données :
$ heroku run python manage.py syncdb
Transfert de données
Nous devons transférer les données de la base de données locale vers la base de données de production.
Installez le module complémentaire Heroku PGBackups :
$ heroku addons:add pgbackups
Videz votre base de données locale :
$ pg_dump -h localhost -Fc library > db.dump
Pour que Heroku puisse accéder au dump db, vous devez le télécharger quelque part sur Internet. Vous pouvez utiliser un site Web personnel, une boîte de dépôt ou S3. Je l'ai simplement téléchargé dans le compartiment S3.
Importez le dump dans Heroku :
$ heroku pgbackups:restore DATABASE http://www.example.com/db.dump
Test
Testons pour nous assurer que tout fonctionne.
Tout d'abord, mettez à jour vos hôtes autorisés sur votre domaine spécifique dans settings.py :
ALLOWED_HOSTS = ['[your-project-name].herokuapp.com']
Découvrez votre application :
$ heroku open
Tissu
Fabric est utilisé pour automatiser le déploiement de votre application.
Installer :
$ pip install fabric
Créez le fichier fab :
$ touch fabfile.py
Ajoutez ensuite le code suivant :
from fabric.api import local
def deploy():
local('pip freeze > requirements.txt')
local('git add .')
print("enter your git commit comment: ")
comment = raw_input()
local('git commit -m "%s"' % comment)
local('git push -u origin master')
local('heroku maintenance:on')
local('git push heroku master')
local('heroku maintenance:off')
Test :
$ fab deploy
Vous avez des questions ou des commentaires ? Rejoignez la discussion ci-dessous.