Dans ce didacticiel, nous allons prendre un simple projet Django local, soutenu par une base de données MySQL, et le convertir 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 simple système de messagerie. Il peut s'agir d'une application todo, 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 un déploiement sur Heroku. J'ai personnellement eu cinq ou six projets où j'ai dû faire exactement cela :convertir un projet local, soutenu par MySQL, en une application en direct sur Heroku.
Configuration
Pré-requis
- 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, 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 readme, initialisez le dépôt Git local, puis PUSH la copie locale vers 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
Mettre à 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 au Whatever
objet. Tuez le serveur.
Convertir de MySQL à Postgres
Remarque : Dans cette situation hypothétique, supposons que vous travailliez sur ce projet depuis un certain temps en utilisant MySQL et que vous souhaitiez 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 nommé 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-le à jour pour votre configuration. Cet exemple ne couvre que la conversion de base. Vous pouvez également inclure ou exclure certaines tables. Voir l'exemple complet ici.
Transférer les données :
$ py-mysql2pgsql -v -f mysql2pgsql.yml
Une fois les données transférées, assurez-vous de mettre à jour votre settings.py fichier :
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 local_settings.py fichier, vous pouvez étendre le settings.py fichier avec les paramètres pertinents pour votre environnement local, tandis que le principal settings.py est utilisé uniquement pour vos environnements de test et de production.
Assurez-vous d'ajouter local_settings.py à votre .gitignore fichier 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 local_settings.py fichier spécifique à leur propre environnement local.
Bien que cette méthode d'utilisation de deux fichiers de paramètres soit une convention depuis un certain nombre d'années, de nombreux développeurs Python utilisent désormais un autre modèle appelé The One True Way. Nous examinerons peut-être ce modèle dans un futur didacticiel.
Mettre à jour settings.py
Nous devons apporter trois modifications à notre settings.py actuel fichier :
Modifier DEBUG
mode à faux :
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 local_settings.py fichier :
$ 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
Ajouter un Profile 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 à outils Heroku :
$ pip install django-toolbelt
Geler les dépendances :
$ pip freeze > requirements.txt
Mettez à jour wsgi.py fichier :
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 cherchez bien? Faisons fonctionner Amazon S3.
Amazon 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ôte tiers, surtout si vous avez une application destinée aux clients. S3 est facile à utiliser et ne nécessite que quelques modifications de votre settings.py fichier.
Installer les dépendances :
$ pip install django-storages
$ pip install boto
Ajouter des storages
et boto
à votre 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 à les définir depuis le terminal chaque fois que nous exécutons le serveur de développement, nous pouvons les définir dans notre virtualenv activate
scénario. Récupérez le nom du compartiment AWS, l'ID de clé d'accès et la clé d'accès secrète à partir 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 bien pris effet :
$ foreman start
Tuez le serveur, puis mettez à jour le requirements.txt fichier :
$ pip freeze > requirements.txt
Pousser vers Github et Heroku
Sauvegardez nos fichiers sur Github avant de les envoyer à Heroku :
$ git add .
$ git commit -m "update project for heroku and S3"
$ git push -u origin master
Créer un projet/dépôt Heroku :
$ heroku create <name>
Nommez-le comme vous voulez.
PUSH vers Heroku :
$ git push heroku master
Envoyez 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 vidage de la base de données, 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 vidage dans Heroku :
$ heroku pgbackups:restore DATABASE http://www.example.com/db.dump
Tester
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 fabfile :
$ 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.