Database
 sql >> Base de données >  >> RDS >> Database

Migrer votre projet Django vers Heroku

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

  1. 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é.
  2. Créez un compte AWS et configurez un compartiment S3 actif.
  3. 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.